simulationjsv2 0.8.4 → 0.10.1

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/TODO.md CHANGED
@@ -1,5 +1,9 @@
1
1
  # TODO
2
2
 
3
+ - [ ] Materials for planes
4
+ - [ ] Transform vertex colors on material
5
+ - [x] Morph objects into other objects
6
+ - [x] `transform` function taking another object and transitioning from current geometry's vertices (positions only)
3
7
  - [x] Change render vertices to use index buffer
4
8
  - [x] Add cull modes
5
9
  - [x] Fix shaders
@@ -1,26 +1,34 @@
1
- import { CircleGeometryParams, CubeGeometryParams, EmptyParams, Spline2dGeometryParams, SquareGeometryParams, Vector3, LineGeometryParams, TraceLinesParams } from './types.js';
2
- import { Vertex } from './utils.js';
1
+ import { CircleGeometryParams, CubeGeometryParams, EmptyParams, Spline2dGeometryParams, SquareGeometryParams, Vector3, LineGeometryParams, TraceLinesParams, LerpFunc } from './types.js';
3
2
  import { CubicBezierCurve2d, SplinePoint2d } from './graphics.js';
4
3
  export declare abstract class Geometry<T extends EmptyParams> {
5
- protected abstract wireframeOrder: number[];
6
- protected abstract triangleOrder: number[];
4
+ private subdivision;
5
+ private subdivisionVertexLimit;
6
+ private fromVertices;
7
+ private currentInterpolate;
8
+ private updated;
9
+ protected wireframeOrder: number[];
10
+ protected triangleOrder: number[];
7
11
  protected abstract params: T;
8
12
  protected vertices: Vector3[];
9
13
  protected topology: 'list' | 'strip';
10
- constructor(vertices?: Vector3[], geometryType?: 'list' | 'strip');
14
+ constructor(geometryType?: 'list' | 'strip');
11
15
  getTopology(): "list" | "strip";
12
- abstract recompute(): void;
16
+ computeVertices(): void;
17
+ compute(): void;
18
+ triangulate(): void;
19
+ setSubdivisions(num: number, vertexLimit?: number): void;
20
+ clearSubdivisions(): void;
21
+ setSubdivisionVertexLimit(limit: number): void;
22
+ clearSubdivisionVertexLimit(): void;
23
+ animateFrom(fromVertices: Vector3[], t: number, f?: LerpFunc): Promise<void>;
13
24
  getIndexes(wireframe: boolean): number[];
14
25
  getVertices(): Vector3[];
26
+ hasUpdated(): boolean;
15
27
  }
16
28
  export declare class PlaneGeometry extends Geometry<EmptyParams> {
17
29
  protected params: {};
18
- protected wireframeOrder: number[];
19
- protected triangleOrder: number[];
20
- private rawVertices;
21
- constructor(vertices: Vertex[]);
22
- recompute(): void;
23
- updateVertices(vertices: Vertex[]): void;
30
+ constructor(vertices: Vector3[]);
31
+ updateVertices(vertices: Vector3[]): void;
24
32
  }
25
33
  export declare class CubeGeometry extends Geometry<CubeGeometryParams> {
26
34
  protected params: CubeGeometryParams;
@@ -30,7 +38,7 @@ export declare class CubeGeometry extends Geometry<CubeGeometryParams> {
30
38
  setWidth(width: number): void;
31
39
  setHeight(height: number): void;
32
40
  setDepth(depth: number): void;
33
- recompute(): void;
41
+ computeVertices(): void;
34
42
  updateSize(width: number, height: number, depth: number): void;
35
43
  }
36
44
  export declare class SquareGeometry extends Geometry<SquareGeometryParams> {
@@ -40,26 +48,24 @@ export declare class SquareGeometry extends Geometry<SquareGeometryParams> {
40
48
  constructor(width: number, height: number);
41
49
  setWidth(width: number): void;
42
50
  setHeight(height: number): void;
43
- recompute(): void;
51
+ computeVertices(): void;
44
52
  }
45
53
  export declare class BlankGeometry extends Geometry<EmptyParams> {
46
- protected wireframeOrder: never[];
47
- protected triangleOrder: never[];
48
54
  protected params: {};
49
55
  constructor();
50
- recompute(): void;
51
56
  }
52
57
  export declare class CircleGeometry extends Geometry<CircleGeometryParams> {
53
- protected wireframeOrder: number[];
54
- protected triangleOrder: number[];
55
58
  protected params: CircleGeometryParams;
56
59
  constructor(radius: number, detail: number);
60
+ setDetail(detail: number): void;
61
+ getDetail(): number;
57
62
  setRadius(radius: number): void;
58
- recompute(): void;
63
+ getRadius(): number;
64
+ computeVertices(): void;
65
+ }
66
+ export declare class OutlineCircleGeometry {
59
67
  }
60
68
  export declare class Spline2dGeometry extends Geometry<Spline2dGeometryParams> {
61
- protected wireframeOrder: number[];
62
- protected triangleOrder: number[];
63
69
  protected params: Spline2dGeometryParams;
64
70
  constructor(points: SplinePoint2d[], thickness: number, detail: number);
65
71
  updateInterpolationStart(start: number): void;
@@ -73,35 +79,31 @@ export declare class Spline2dGeometry extends Geometry<Spline2dGeometryParams> {
73
79
  getVertexInterpolations(): number[];
74
80
  getCurveVertexIndices(): number[];
75
81
  private computeCurves;
76
- recompute(): void;
82
+ computeVertices(): void;
77
83
  }
78
84
  export declare class Line2dGeometry extends Geometry<LineGeometryParams> {
79
85
  protected wireframeOrder: number[];
80
86
  protected triangleOrder: number[];
81
87
  protected params: LineGeometryParams;
82
88
  constructor(pos: Vector3, to: Vector3, thickness: number);
83
- recompute(): void;
89
+ computeVertices(): void;
84
90
  }
85
91
  export declare class Line3dGeometry extends Geometry<LineGeometryParams> {
86
92
  protected wireframeOrder: number[];
87
93
  protected triangleOrder: number[];
88
94
  protected params: LineGeometryParams;
89
95
  constructor(pos: Vector3, to: Vector3, thickness: number);
90
- recompute(): void;
96
+ computeVertices(): void;
91
97
  }
92
98
  export declare class PolygonGeometry extends Geometry<EmptyParams> {
93
- protected wireframeOrder: number[];
94
- protected triangleOrder: number[];
95
99
  protected params: {};
96
100
  constructor(vertices: Vector3[]);
97
- recompute(): void;
101
+ computeVertices(): void;
98
102
  }
99
- export declare class TraceLines2dGeometry extends Geometry<TraceLinesParams> {
100
- protected wireframeOrder: number[];
101
- protected triangleOrder: never[];
103
+ export declare class TraceLinesGeometry extends Geometry<TraceLinesParams> {
102
104
  protected params: TraceLinesParams;
103
105
  constructor(maxLen?: number);
104
- recompute(): void;
106
+ triangulate(): void;
105
107
  getVertexCount(): number;
106
108
  getOrder(_: boolean): readonly [Vector3[], number[]];
107
109
  addVertex(vert: Vector3): void;
package/dist/geometry.js CHANGED
@@ -1,42 +1,150 @@
1
1
  import { mat4, vec2, vec3 } from 'wgpu-matrix';
2
- import { cloneBuf, matrix4, vector2, vector2FromVector3, vector3, vector3FromVector2 } from './utils.js';
2
+ import { cloneBuf, cloneVectors, matrix4, transitionValues, vector2, vector2FromVector3, vector3, vector3FromVector2 } from './utils.js';
3
3
  import { CubicBezierCurve2d } from './graphics.js';
4
4
  import { createIndexArray, lossyTriangulate, lossyTriangulateStrip, triangulateWireFrameOrder } from './internalUtils.js';
5
5
  export class Geometry {
6
+ subdivision = 0;
7
+ subdivisionVertexLimit = null;
8
+ // null if not animating, assumed to be at least the length of vertices
9
+ fromVertices = null;
10
+ currentInterpolate = 0; // stops animating after 1
11
+ updated;
12
+ wireframeOrder;
13
+ triangleOrder;
6
14
  vertices;
7
15
  topology;
8
- constructor(vertices = [], geometryType = 'list') {
9
- this.vertices = vertices;
16
+ constructor(geometryType = 'list') {
17
+ this.vertices = [];
10
18
  this.topology = geometryType;
19
+ this.updated = true;
20
+ this.wireframeOrder = [];
21
+ this.triangleOrder = [];
11
22
  }
12
23
  getTopology() {
13
24
  return this.topology;
14
25
  }
26
+ computeVertices() { }
27
+ compute() {
28
+ this.computeVertices();
29
+ this.updated = false;
30
+ // handle subdivisions
31
+ let initialVertices = [...this.vertices];
32
+ outer: for (let i = 0; i < this.subdivision; i++) {
33
+ const initialLength = initialVertices.length;
34
+ for (let j = 0; j < initialLength - 1; j++) {
35
+ if (this.subdivisionVertexLimit && this.vertices.length >= this.subdivisionVertexLimit)
36
+ break outer;
37
+ const vert = initialVertices[j];
38
+ const nextVert = initialVertices[j + 1];
39
+ const newVert = cloneBuf(nextVert);
40
+ vec3.add(newVert, vert, newVert);
41
+ vec3.divScalar(newVert, 2, newVert);
42
+ this.vertices.splice(j * 2 + 1, 0, newVert);
43
+ }
44
+ if (initialLength >= 2) {
45
+ const first = initialVertices[0];
46
+ const last = initialVertices[initialVertices.length - 1];
47
+ const newVert = cloneBuf(first);
48
+ vec3.add(newVert, last, newVert);
49
+ vec3.divScalar(newVert, 2, newVert);
50
+ this.vertices.push(newVert);
51
+ }
52
+ initialVertices = [...this.vertices];
53
+ }
54
+ // handle animation
55
+ if (this.fromVertices) {
56
+ const initialFrom = cloneVectors(this.fromVertices);
57
+ const changes = [];
58
+ for (let i = 0; i < this.vertices.length; i++) {
59
+ const from = initialFrom[i];
60
+ const to = this.vertices[i];
61
+ const diff = cloneBuf(to);
62
+ vec3.sub(diff, from, diff);
63
+ changes.push(diff);
64
+ }
65
+ for (let i = this.vertices.length; i < initialFrom.length; i++) {
66
+ const from = initialFrom[i];
67
+ const to = this.vertices[this.vertices.length - 1];
68
+ const diff = cloneBuf(to);
69
+ vec3.sub(diff, from, diff);
70
+ changes.push(diff);
71
+ }
72
+ for (let i = 0; i < initialFrom.length; i++) {
73
+ const diff = changes[i];
74
+ vec3.mulScalar(diff, this.currentInterpolate, diff);
75
+ vec3.add(initialFrom[i], diff, initialFrom[i]);
76
+ }
77
+ this.vertices = initialFrom;
78
+ }
79
+ if (this.fromVertices || this.subdivision > 0)
80
+ this.triangulate();
81
+ }
82
+ triangulate() {
83
+ this.wireframeOrder = triangulateWireFrameOrder(this.vertices.length);
84
+ const indexArray = createIndexArray(this.vertices.length);
85
+ if (this.topology === 'list') {
86
+ this.triangleOrder = lossyTriangulate(indexArray).flat();
87
+ }
88
+ else {
89
+ this.triangleOrder = lossyTriangulateStrip(indexArray);
90
+ }
91
+ }
92
+ setSubdivisions(num, vertexLimit) {
93
+ if (num >= 0) {
94
+ this.subdivision = num;
95
+ if (vertexLimit)
96
+ this.subdivisionVertexLimit = vertexLimit;
97
+ }
98
+ }
99
+ clearSubdivisions() {
100
+ this.subdivision = 0;
101
+ this.clearSubdivisionVertexLimit();
102
+ }
103
+ setSubdivisionVertexLimit(limit) {
104
+ this.subdivisionVertexLimit = limit;
105
+ }
106
+ clearSubdivisionVertexLimit() {
107
+ this.subdivisionVertexLimit = null;
108
+ }
109
+ animateFrom(fromVertices, t, f) {
110
+ this.fromVertices = fromVertices;
111
+ // ensure at least the length of vertices
112
+ if (fromVertices.length < this.vertices.length) {
113
+ const initialLen = fromVertices.length;
114
+ for (let i = 0; i < this.vertices.length - initialLen; i++) {
115
+ const last = cloneBuf(fromVertices[fromVertices.length - 1]);
116
+ this.fromVertices.push(last);
117
+ }
118
+ }
119
+ return transitionValues((p) => {
120
+ this.currentInterpolate += p;
121
+ this.updated = true;
122
+ }, () => {
123
+ this.currentInterpolate = 0;
124
+ this.fromVertices = null;
125
+ this.updated = true;
126
+ }, t, f);
127
+ }
15
128
  getIndexes(wireframe) {
16
129
  return wireframe ? this.wireframeOrder : this.triangleOrder;
17
130
  }
18
131
  getVertices() {
19
132
  return this.vertices;
20
133
  }
134
+ hasUpdated() {
135
+ return this.updated;
136
+ }
21
137
  }
22
138
  export class PlaneGeometry extends Geometry {
23
139
  params = {};
24
- wireframeOrder;
25
- triangleOrder;
26
- rawVertices;
27
140
  constructor(vertices) {
28
- super([], 'strip');
29
- this.wireframeOrder = [];
30
- this.triangleOrder = [];
31
- this.rawVertices = vertices;
32
- this.updateVertices(vertices);
141
+ super('strip');
142
+ this.vertices = vertices;
143
+ this.triangulate();
33
144
  }
34
- recompute() { }
35
145
  updateVertices(vertices) {
36
- this.rawVertices = vertices;
37
- this.vertices = vertices.map((vertex) => vertex.getPos());
38
- this.wireframeOrder = triangulateWireFrameOrder(this.vertices.length);
39
- this.triangleOrder = lossyTriangulateStrip(createIndexArray(this.rawVertices.length));
146
+ this.vertices = vertices;
147
+ this.triangulate();
40
148
  }
41
149
  }
42
150
  export class CubeGeometry extends Geometry {
@@ -58,7 +166,7 @@ export class CubeGeometry extends Geometry {
58
166
  height,
59
167
  depth
60
168
  };
61
- this.recompute();
169
+ this.computeVertices();
62
170
  }
63
171
  setWidth(width) {
64
172
  this.params.width = width;
@@ -69,7 +177,7 @@ export class CubeGeometry extends Geometry {
69
177
  setDepth(depth) {
70
178
  this.params.depth = depth;
71
179
  }
72
- recompute() {
180
+ computeVertices() {
73
181
  const { width, height, depth } = this.params;
74
182
  this.vertices = [
75
183
  // front face
@@ -95,12 +203,12 @@ export class SquareGeometry extends Geometry {
95
203
  triangleOrder = [0, 3, 1, 2];
96
204
  params;
97
205
  constructor(width, height) {
98
- super([], 'strip');
206
+ super('strip');
99
207
  this.params = {
100
208
  width,
101
209
  height
102
210
  };
103
- this.recompute();
211
+ this.computeVertices();
104
212
  }
105
213
  setWidth(width) {
106
214
  this.params.width = width;
@@ -108,61 +216,60 @@ export class SquareGeometry extends Geometry {
108
216
  setHeight(height) {
109
217
  this.params.height = height;
110
218
  }
111
- recompute() {
219
+ computeVertices() {
112
220
  this.vertices = [
113
- vector3(-this.params.width, this.params.height),
114
- vector3(this.params.width, this.params.height),
115
- vector3(this.params.width, -this.params.height),
116
- vector3(-this.params.width, -this.params.height)
221
+ vector3(-this.params.width / 2, this.params.height / 2),
222
+ vector3(this.params.width / 2, this.params.height / 2),
223
+ vector3(this.params.width / 2, -this.params.height / 2),
224
+ vector3(-this.params.width / 2, -this.params.height / 2)
117
225
  ];
118
226
  }
119
227
  }
120
228
  export class BlankGeometry extends Geometry {
121
- wireframeOrder = [];
122
- triangleOrder = [];
123
229
  params = {};
124
230
  constructor() {
125
231
  super();
126
232
  }
127
- recompute() { }
128
233
  }
129
234
  export class CircleGeometry extends Geometry {
130
- wireframeOrder;
131
- triangleOrder;
132
235
  params;
133
236
  constructor(radius, detail) {
134
- super([], 'strip');
135
- this.wireframeOrder = [];
136
- this.triangleOrder = [];
237
+ super('strip');
137
238
  this.params = { radius, detail };
138
- this.recompute();
239
+ this.computeVertices();
240
+ }
241
+ setDetail(detail) {
242
+ this.params.detail = detail;
243
+ }
244
+ getDetail() {
245
+ return this.params.detail;
139
246
  }
140
247
  setRadius(radius) {
141
248
  this.params.radius = radius;
142
249
  }
143
- recompute() {
250
+ getRadius() {
251
+ return this.params.radius;
252
+ }
253
+ computeVertices() {
144
254
  const vertices = [];
145
255
  const rotationInc = (Math.PI * 2) / this.params.detail;
146
256
  for (let i = 0; i < this.params.detail; i++) {
147
257
  const mat = matrix4();
148
- mat4.rotateZ(mat, rotationInc * i, mat);
258
+ mat4.rotateZ(mat, -rotationInc * i + Math.PI / 2, mat);
149
259
  const vec = vector3(this.params.radius);
150
260
  vec3.transformMat4(vec, mat, vec);
151
261
  vertices.push(vector3(vec[0], vec[1], vec[2]));
152
262
  }
153
263
  this.vertices = vertices;
154
- this.triangleOrder = lossyTriangulate(createIndexArray(this.vertices.length)).flat();
155
- this.wireframeOrder = triangulateWireFrameOrder(this.vertices.length);
264
+ this.triangulate();
156
265
  }
157
266
  }
267
+ export class OutlineCircleGeometry {
268
+ }
158
269
  export class Spline2dGeometry extends Geometry {
159
- wireframeOrder;
160
- triangleOrder;
161
270
  params;
162
271
  constructor(points, thickness, detail) {
163
- super([], 'strip');
164
- this.wireframeOrder = [];
165
- this.triangleOrder = [];
272
+ super('strip');
166
273
  this.params = {
167
274
  points: points,
168
275
  curves: [],
@@ -175,7 +282,7 @@ export class Spline2dGeometry extends Geometry {
175
282
  curveVertexIndices: []
176
283
  };
177
284
  this.computeCurves();
178
- this.recompute();
285
+ this.computeVertices();
179
286
  }
180
287
  updateInterpolationStart(start) {
181
288
  this.params.interpolateStart = Math.min(1, Math.max(0, start));
@@ -238,7 +345,7 @@ export class Spline2dGeometry extends Geometry {
238
345
  this.params.curves.push(curve);
239
346
  }
240
347
  }
241
- recompute() {
348
+ computeVertices() {
242
349
  this.vertices = [];
243
350
  this.params.vertexInterpolations = [];
244
351
  this.params.curveVertexIndices = [];
@@ -291,8 +398,7 @@ export class Spline2dGeometry extends Geometry {
291
398
  }
292
399
  }
293
400
  this.vertices = verticesTop.concat(verticesBottom);
294
- this.triangleOrder = lossyTriangulateStrip(createIndexArray(this.vertices.length));
295
- this.wireframeOrder = triangulateWireFrameOrder(this.vertices.length);
401
+ this.triangulate();
296
402
  }
297
403
  }
298
404
  export class Line2dGeometry extends Geometry {
@@ -300,17 +406,17 @@ export class Line2dGeometry extends Geometry {
300
406
  triangleOrder = [0, 3, 1, 2];
301
407
  params;
302
408
  constructor(pos, to, thickness) {
303
- super([], 'strip');
409
+ super('strip');
304
410
  this.params = {
305
411
  pos,
306
412
  to,
307
413
  thickness
308
414
  };
309
415
  }
310
- recompute() {
416
+ computeVertices() {
311
417
  const normal = vector2(-this.params.to[1], this.params.to[0]);
312
418
  vec2.normalize(normal, normal);
313
- vec2.scale(normal, this.params.thickness / 2, normal);
419
+ vec2.scale(normal, this.params.thickness, normal);
314
420
  this.vertices = [
315
421
  vector3(-normal[0], -normal[1]),
316
422
  vector3(normal[0], normal[1]),
@@ -324,14 +430,14 @@ export class Line3dGeometry extends Geometry {
324
430
  triangleOrder = [0, 3, 1, 2];
325
431
  params;
326
432
  constructor(pos, to, thickness) {
327
- super([], 'strip');
433
+ super('strip');
328
434
  this.params = {
329
435
  pos,
330
436
  to,
331
437
  thickness
332
438
  };
333
439
  }
334
- recompute() {
440
+ computeVertices() {
335
441
  const normal = vector2(-this.params.to[1], this.params.to[0]);
336
442
  vec2.normalize(normal, normal);
337
443
  vec2.scale(normal, this.params.thickness / 2, normal);
@@ -344,32 +450,25 @@ export class Line3dGeometry extends Geometry {
344
450
  }
345
451
  }
346
452
  export class PolygonGeometry extends Geometry {
347
- wireframeOrder;
348
- triangleOrder;
349
453
  params = {};
350
454
  constructor(vertices) {
351
- super([], 'strip');
352
- this.wireframeOrder = [];
353
- this.triangleOrder = [];
455
+ super('strip');
354
456
  this.vertices = vertices;
355
- this.recompute();
457
+ this.computeVertices();
356
458
  }
357
- recompute() {
358
- this.triangleOrder = lossyTriangulateStrip(createIndexArray(this.vertices.length));
359
- this.wireframeOrder = triangulateWireFrameOrder(this.vertices.length);
459
+ computeVertices() {
460
+ this.triangulate();
360
461
  }
361
462
  }
362
- export class TraceLines2dGeometry extends Geometry {
363
- wireframeOrder = [];
364
- triangleOrder = [];
463
+ export class TraceLinesGeometry extends Geometry {
365
464
  params;
366
465
  constructor(maxLen) {
367
- super([], 'strip');
466
+ super('strip');
368
467
  this.params = {
369
468
  maxLength: maxLen ?? null
370
469
  };
371
470
  }
372
- recompute() { }
471
+ triangulate() { }
373
472
  getVertexCount() {
374
473
  return this.vertices.length;
375
474
  }
package/dist/globals.d.ts CHANGED
@@ -1,5 +1,7 @@
1
1
  /// <reference types="@webgpu/types" />
2
2
  import { Shader } from './shaders.js';
3
+ import { Simulation } from './simulation.js';
4
+ import { Color } from './utils.js';
3
5
  declare class Logger {
4
6
  constructor();
5
7
  private fmt;
@@ -10,8 +12,15 @@ declare class Logger {
10
12
  }
11
13
  export declare const logger: Logger;
12
14
  export declare class GlobalInfo {
15
+ private canvas;
13
16
  private device;
17
+ private defaultColor;
14
18
  constructor();
19
+ setDefaultColor(color: Color): void;
20
+ getDefaultColor(): Color;
21
+ setCanvas(canvas: Simulation): void;
22
+ errorGetCanvas(): Simulation;
23
+ getCanvas(): Simulation | null;
15
24
  setDevice(device: GPUDevice): void;
16
25
  errorGetDevice(): GPUDevice;
17
26
  getDevice(): GPUDevice | null;
package/dist/globals.js CHANGED
@@ -1,4 +1,5 @@
1
1
  import { createPipeline } from './internalUtils.js';
2
+ import { color } from './utils.js';
2
3
  class Logger {
3
4
  constructor() { }
4
5
  fmt(msg) {
@@ -19,9 +20,30 @@ class Logger {
19
20
  }
20
21
  export const logger = new Logger();
21
22
  export class GlobalInfo {
23
+ canvas;
22
24
  device;
25
+ defaultColor;
23
26
  constructor() {
27
+ this.canvas = null;
24
28
  this.device = null;
29
+ this.defaultColor = null;
30
+ }
31
+ setDefaultColor(color) {
32
+ this.defaultColor = color;
33
+ }
34
+ getDefaultColor() {
35
+ return this.defaultColor?.clone() ?? color();
36
+ }
37
+ setCanvas(canvas) {
38
+ this.canvas = canvas;
39
+ }
40
+ errorGetCanvas() {
41
+ if (!this.canvas)
42
+ throw logger.error('Canvas is null');
43
+ return this.canvas;
44
+ }
45
+ getCanvas() {
46
+ return this.canvas;
25
47
  }
26
48
  setDevice(device) {
27
49
  this.device = device;
@@ -1,7 +1,7 @@
1
1
  /// <reference types="@webgpu/types" />
2
2
  import type { Vector2, Vector3, LerpFunc, Mat4 } from './types.js';
3
3
  import { Vertex, Color } from './utils.js';
4
- import { BlankGeometry, CircleGeometry, CubeGeometry, Geometry, Line2dGeometry, Line3dGeometry, PlaneGeometry, PolygonGeometry, Spline2dGeometry, SquareGeometry, TraceLines2dGeometry as TraceLinesGeometry } from './geometry.js';
4
+ import { BlankGeometry, CircleGeometry, CubeGeometry, Geometry, Line2dGeometry, Line3dGeometry, PlaneGeometry, PolygonGeometry, Spline2dGeometry, SquareGeometry, TraceLinesGeometry as TraceLinesGeometry } from './geometry.js';
5
5
  import { Float32ArrayCache } from './internalUtils.js';
6
6
  import { Shader } from './shaders.js';
7
7
  import { Material } from './materials.js';
@@ -26,9 +26,6 @@ export declare abstract class SimulationElement3d {
26
26
  isInstanced: boolean;
27
27
  is3d: boolean;
28
28
  isEmpty: boolean;
29
- /**
30
- * @param pos - Expected to be adjusted to devicePixelRatio before reaching constructor
31
- */
32
29
  constructor(pos: Vector3, rotation: Vector3, color?: Color);
33
30
  getId(): string | null;
34
31
  setId(id: string): void;
@@ -44,6 +41,11 @@ export declare abstract class SimulationElement3d {
44
41
  getParent(): SimulationElement3d | null;
45
42
  getCullMode(): GPUCullMode;
46
43
  setCullMode(mode: GPUCullMode): void;
44
+ subDivideTo(limit: number): void;
45
+ setSubdivisions(divisions: number, vertexLimit?: number): void;
46
+ clearSubdivisions(): void;
47
+ setSubdivisionVertexLimit(limit: number): void;
48
+ clearSubdivisionVertexLimit(): void;
47
49
  setCenterOffset(offset: Vector3): void;
48
50
  getShader(): Shader;
49
51
  setShader(shader: Shader): void;
@@ -62,17 +64,21 @@ export declare abstract class SimulationElement3d {
62
64
  setWireframe(wireframe: boolean): void;
63
65
  isWireframe(): boolean;
64
66
  getMaterial(): Material;
67
+ getGeometry(): Geometry<object>;
68
+ getVertices(): Vector3[];
65
69
  getRelativePos(): Vector3;
66
70
  getPos(): Vector3;
67
71
  getRotation(): Vector3;
68
72
  getCenterOffset(): Vector3;
69
73
  fill(newColor: Color, t?: number, f?: LerpFunc): Promise<void>;
70
- move(amount: Vector3, t?: number, f?: LerpFunc, fromDevicePixelRatio?: boolean): Promise<void>;
71
- moveTo(pos: Vector3, t?: number, f?: LerpFunc, fromDevicePixelRatio?: boolean): Promise<void>;
74
+ move(amount: Vector3, t?: number, f?: LerpFunc): Promise<void>;
75
+ moveTo(pos: Vector3, t?: number, f?: LerpFunc): Promise<void>;
72
76
  rotateChildren(angle: Vector3): void;
73
77
  rotate(amount: Vector3, t?: number, f?: LerpFunc): Promise<void>;
74
78
  rotateTo(rot: Vector3, t?: number, f?: LerpFunc): Promise<void>;
79
+ animateVerticesFrom(vertices: Vector3[], t: number, f?: LerpFunc): Promise<void>;
75
80
  getVertexCount(): number;
81
+ getTreeVertexCount(): number;
76
82
  getIndexCount(): number;
77
83
  writeBuffers(): void;
78
84
  getVertexBuffer(): Float32Array;
@@ -117,12 +123,14 @@ export declare class Square extends SimulationElement2d {
117
123
  }
118
124
  export declare class Circle extends SimulationElement2d {
119
125
  protected geometry: CircleGeometry;
120
- private radius;
121
- private detail;
122
126
  constructor(pos: Vector2, radius: number, color?: Color, detail?: number);
127
+ setDetail(detail: number): void;
123
128
  setRadius(num: number, t?: number, f?: LerpFunc): Promise<void>;
124
129
  scale(amount: number, t?: number, f?: LerpFunc): Promise<void>;
125
130
  }
131
+ export declare class OutlineCircle extends Circle {
132
+ constructor(pos: Vector2, radius: number, color?: Color, detail?: number);
133
+ }
126
134
  export declare class Polygon extends SimulationElement2d {
127
135
  protected geometry: PolygonGeometry;
128
136
  constructor(pos: Vector2, vertices: Vertex[], color?: Color, rotation?: number);
@@ -227,7 +235,7 @@ export declare class Instance<T extends SimulationElement3d> extends SimulationE
227
235
  getInstances(): Mat4[];
228
236
  getNumInstances(): number;
229
237
  getInstanceBuffer(): GPUBuffer;
230
- getVertexCount(): number;
238
+ getTreeVertexCount(): number;
231
239
  getIndexCount(): number;
232
240
  getGeometryTopology(): "list" | "strip";
233
241
  getVertexBuffer(): Float32Array;
package/dist/graphics.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { vec3, mat4, vec2 } from 'wgpu-matrix';
2
- import { cloneBuf, vector2, vector3, Color, vector2FromVector3, matrix4, vector3FromVector2, distance2d, color, interpolateColors } from './utils.js';
3
- import { BlankGeometry, CircleGeometry, CubeGeometry, Line2dGeometry, Line3dGeometry, PlaneGeometry, PolygonGeometry, Spline2dGeometry, SquareGeometry, TraceLines2dGeometry as TraceLinesGeometry } from './geometry.js';
4
- import { Float32ArrayCache, internalTransitionValues, posTo2dScreen, vector3ToPixelRatio } from './internalUtils.js';
2
+ import { cloneBuf, vector2, vector3, vector2FromVector3, matrix4, vector3FromVector2, distance2d, interpolateColors } from './utils.js';
3
+ import { BlankGeometry, CircleGeometry, CubeGeometry, Line2dGeometry, Line3dGeometry, PlaneGeometry, PolygonGeometry, Spline2dGeometry, SquareGeometry, TraceLinesGeometry as TraceLinesGeometry } from './geometry.js';
4
+ import { Float32ArrayCache, internalTransitionValues, posTo2dScreen } from './internalUtils.js';
5
5
  import { mat4ByteLength, modelProjMatOffset } from './constants.js';
6
6
  import { MemoBuffer } from './buffers.js';
7
7
  import { globalInfo, logger, pipelineCache } from './globals.js';
@@ -27,10 +27,7 @@ export class SimulationElement3d {
27
27
  isInstanced = false;
28
28
  is3d = true;
29
29
  isEmpty = false;
30
- /**
31
- * @param pos - Expected to be adjusted to devicePixelRatio before reaching constructor
32
- */
33
- constructor(pos, rotation, color = new Color()) {
30
+ constructor(pos, rotation, color = globalInfo.getDefaultColor()) {
34
31
  this.pos = pos;
35
32
  this.centerOffset = vector3();
36
33
  this.vertexCache = new Float32ArrayCache();
@@ -44,7 +41,7 @@ export class SimulationElement3d {
44
41
  this.prevInfo = null;
45
42
  this.shader = defaultShader;
46
43
  this.material = new BasicMaterial(color);
47
- this.cullMode = 'back';
44
+ this.cullMode = 'none';
48
45
  this.id = null;
49
46
  }
50
47
  getId() {
@@ -102,6 +99,32 @@ export class SimulationElement3d {
102
99
  setCullMode(mode) {
103
100
  this.cullMode = mode;
104
101
  }
102
+ subDivideTo(limit) {
103
+ this.geometry.setSubdivisions(Infinity, limit);
104
+ this.vertexCache.updated();
105
+ this.geometry.compute();
106
+ }
107
+ /// may have unexpeced behavior for 3d shapes
108
+ setSubdivisions(divisions, vertexLimit) {
109
+ this.geometry.setSubdivisions(divisions, vertexLimit);
110
+ this.vertexCache.updated();
111
+ this.geometry.compute();
112
+ }
113
+ clearSubdivisions() {
114
+ this.geometry.clearSubdivisions();
115
+ this.vertexCache.updated();
116
+ this.geometry.compute();
117
+ }
118
+ setSubdivisionVertexLimit(limit) {
119
+ this.geometry.setSubdivisionVertexLimit(limit);
120
+ this.vertexCache.updated();
121
+ this.geometry.compute();
122
+ }
123
+ clearSubdivisionVertexLimit() {
124
+ this.geometry.clearSubdivisionVertexLimit();
125
+ this.vertexCache.updated();
126
+ this.geometry.compute();
127
+ }
105
128
  setCenterOffset(offset) {
106
129
  this.centerOffset = offset;
107
130
  }
@@ -150,7 +173,8 @@ export class SimulationElement3d {
150
173
  if (!this.parent)
151
174
  return;
152
175
  this.parent.mirrorParentTransforms3d(mat);
153
- mat4.translate(mat, this.parent.getRelativePos(), mat);
176
+ const pos = cloneBuf(this.parent.getRelativePos());
177
+ mat4.translate(mat, pos, mat);
154
178
  const parentRot = this.parent.getRotation();
155
179
  mat4.rotateZ(mat, parentRot[2], mat);
156
180
  mat4.rotateY(mat, parentRot[1], mat);
@@ -161,7 +185,8 @@ export class SimulationElement3d {
161
185
  if (this.parent) {
162
186
  this.mirrorParentTransforms3d(this.modelMatrix);
163
187
  }
164
- mat4.translate(this.modelMatrix, this.pos, this.modelMatrix);
188
+ const pos = cloneBuf(this.pos);
189
+ mat4.translate(this.modelMatrix, pos, this.modelMatrix);
165
190
  mat4.rotateZ(this.modelMatrix, this.rotation[2], this.modelMatrix);
166
191
  mat4.rotateY(this.modelMatrix, this.rotation[1], this.modelMatrix);
167
192
  mat4.rotateX(this.modelMatrix, this.rotation[0], this.modelMatrix);
@@ -176,7 +201,8 @@ export class SimulationElement3d {
176
201
  this.parent.mirrorParentTransforms2d(mat);
177
202
  const parentRot = this.parent.getRotation();
178
203
  mat4.rotateZ(mat, parentRot[2], mat);
179
- mat4.translate(mat, this.pos, mat);
204
+ const pos = cloneBuf(this.pos);
205
+ mat4.translate(mat, pos, mat);
180
206
  }
181
207
  updateModelMatrix2d() {
182
208
  mat4.identity(this.modelMatrix);
@@ -205,6 +231,12 @@ export class SimulationElement3d {
205
231
  getMaterial() {
206
232
  return this.material;
207
233
  }
234
+ getGeometry() {
235
+ return this.geometry;
236
+ }
237
+ getVertices() {
238
+ return this.geometry.getVertices();
239
+ }
208
240
  getRelativePos() {
209
241
  return this.pos;
210
242
  }
@@ -235,10 +267,8 @@ export class SimulationElement3d {
235
267
  this.vertexCache.updated();
236
268
  }, t, f);
237
269
  }
238
- move(amount, t = 0, f, fromDevicePixelRatio = false) {
270
+ move(amount, t = 0, f) {
239
271
  const tempAmount = cloneBuf(amount);
240
- if (!fromDevicePixelRatio)
241
- vector3ToPixelRatio(tempAmount);
242
272
  const finalPos = cloneBuf(this.pos);
243
273
  vec3.add(finalPos, tempAmount, finalPos);
244
274
  return internalTransitionValues((p) => {
@@ -249,10 +279,8 @@ export class SimulationElement3d {
249
279
  this.pos = finalPos;
250
280
  }, t, f);
251
281
  }
252
- moveTo(pos, t = 0, f, fromDevicePixelRatio = false) {
282
+ moveTo(pos, t = 0, f) {
253
283
  const tempPos = cloneBuf(pos);
254
- if (!fromDevicePixelRatio)
255
- vector3ToPixelRatio(tempPos);
256
284
  const diff = vector3();
257
285
  vec3.sub(tempPos, this.pos, diff);
258
286
  return internalTransitionValues((p) => {
@@ -293,13 +321,22 @@ export class SimulationElement3d {
293
321
  this.rotation = cloneBuf(rot);
294
322
  }, t, f);
295
323
  }
324
+ animateVerticesFrom(vertices, t, f) {
325
+ if (this.getVertexCount() !== vertices.length) {
326
+ throw logger.error(`Expected vertex array of same length, found ${this.getVertexCount()}::${vertices.length}`);
327
+ }
328
+ return this.geometry.animateFrom(vertices, t, f);
329
+ }
296
330
  getVertexCount() {
331
+ return this.getVertices().length;
332
+ }
333
+ getTreeVertexCount() {
297
334
  if (this.vertexCache.shouldUpdate()) {
298
- this.geometry.recompute();
335
+ this.geometry.compute();
299
336
  }
300
337
  let vertexCount = this.geometry.getIndexes(this.isWireframe()).length;
301
338
  for (let i = 0; i < this.children.length; i++) {
302
- vertexCount += this.children[i].getVertexCount();
339
+ vertexCount += this.children[i].getTreeVertexCount();
303
340
  }
304
341
  return vertexCount;
305
342
  }
@@ -314,12 +351,11 @@ export class SimulationElement3d {
314
351
  this.shader.writeBuffers(this);
315
352
  }
316
353
  getVertexBuffer() {
317
- if (this.vertexCache.shouldUpdate()) {
318
- this.geometry.recompute();
354
+ if (this.vertexCache.shouldUpdate() || this.geometry.hasUpdated()) {
355
+ this.geometry.compute();
319
356
  const vertices = this.geometry.getVertices();
320
357
  const stride = this.shader.getBufferLength();
321
358
  const vertexBuffer = new Float32Array(vertices.length * stride);
322
- // const shader = this.isWireframe() ? defaultShader : this.shader;
323
359
  for (let i = 0; i < vertices.length; i++) {
324
360
  this.shader.setVertexInfo(this, vertexBuffer, vertices[i], i, i * stride);
325
361
  }
@@ -349,7 +385,6 @@ export class SimulationElement2d extends SimulationElement3d {
349
385
  is3d = false;
350
386
  constructor(pos, rotation = vector3(), color) {
351
387
  super(vector3FromVector2(pos), rotation, color);
352
- vector3ToPixelRatio(this.pos);
353
388
  }
354
389
  rotate2d(amount, t = 0, f) {
355
390
  return super.rotate(vector3(0, 0, amount), t, f);
@@ -369,8 +404,7 @@ export class Plane extends SimulationElement3d {
369
404
  super(pos, rotation, color);
370
405
  this.rotation = rotation;
371
406
  this.points = points;
372
- this.geometry = new PlaneGeometry(points);
373
- this.cullMode = 'none';
407
+ this.geometry = new PlaneGeometry(points.map((vert) => vert.getPos()));
374
408
  }
375
409
  setPoints(newPoints) {
376
410
  this.points = newPoints;
@@ -387,8 +421,8 @@ export class Square extends SimulationElement2d {
387
421
  */
388
422
  constructor(pos, width, height, color, rotation) {
389
423
  super(pos, vector3(0, 0, rotation), color);
390
- this.width = width / devicePixelRatio;
391
- this.height = height / devicePixelRatio;
424
+ this.width = width;
425
+ this.height = height;
392
426
  this.geometry = new SquareGeometry(this.width, this.height);
393
427
  }
394
428
  getWidth() {
@@ -443,7 +477,6 @@ export class Square extends SimulationElement2d {
443
477
  }, t, f);
444
478
  }
445
479
  setWidth(num, t = 0, f) {
446
- num *= devicePixelRatio;
447
480
  const diffWidth = num - this.width;
448
481
  return internalTransitionValues((p) => {
449
482
  this.width += diffWidth * p;
@@ -456,7 +489,6 @@ export class Square extends SimulationElement2d {
456
489
  }, t, f);
457
490
  }
458
491
  setHeight(num, t = 0, f) {
459
- num *= devicePixelRatio;
460
492
  const diffHeight = num - this.height;
461
493
  return internalTransitionValues((p) => {
462
494
  this.height += diffHeight * p;
@@ -471,51 +503,57 @@ export class Square extends SimulationElement2d {
471
503
  }
472
504
  export class Circle extends SimulationElement2d {
473
505
  geometry;
474
- radius;
475
- detail;
476
506
  constructor(pos, radius, color, detail = 50) {
477
507
  super(pos, vector3(), color);
478
- this.radius = radius * devicePixelRatio;
479
- this.detail = detail;
480
- this.geometry = new CircleGeometry(this.radius, this.detail);
508
+ this.geometry = new CircleGeometry(radius, detail);
509
+ }
510
+ setDetail(detail) {
511
+ this.geometry.setDetail(detail);
481
512
  }
482
513
  setRadius(num, t = 0, f) {
483
- num *= devicePixelRatio;
484
- const diff = num - this.radius;
514
+ let radius = this.geometry.getRadius();
515
+ const diff = num - radius;
485
516
  return internalTransitionValues((p) => {
486
- this.radius += diff * p;
487
- this.geometry.setRadius(this.radius);
517
+ radius += diff * p;
518
+ this.geometry.setRadius(radius);
488
519
  this.vertexCache.updated();
489
520
  }, () => {
490
- this.radius = num;
491
- this.geometry.setRadius(this.radius);
521
+ radius = num;
522
+ this.geometry.setRadius(radius);
492
523
  this.vertexCache.updated();
493
524
  }, t, f);
494
525
  }
495
526
  scale(amount, t = 0, f) {
496
- const finalRadius = this.radius * amount;
497
- const diff = finalRadius - this.radius;
527
+ let radius = this.geometry.getRadius();
528
+ const finalRadius = radius * amount;
529
+ const diff = finalRadius - radius;
498
530
  return internalTransitionValues((p) => {
499
- this.radius += diff * p;
500
- this.geometry.setRadius(this.radius);
531
+ radius += diff * p;
532
+ this.geometry.setRadius(radius);
501
533
  this.vertexCache.updated();
502
534
  }, () => {
503
- this.radius = finalRadius;
504
- this.geometry.setRadius(this.radius);
535
+ radius = finalRadius;
536
+ this.geometry.setRadius(radius);
505
537
  this.vertexCache.updated();
506
538
  }, t, f);
507
539
  }
508
540
  }
541
+ export class OutlineCircle extends Circle {
542
+ constructor(pos, radius, color, detail) {
543
+ super(pos, radius, color, detail);
544
+ // this.geometry = new OutlineCircleGeometry();
545
+ }
546
+ }
509
547
  export class Polygon extends SimulationElement2d {
510
548
  geometry;
511
549
  constructor(pos, vertices, color, rotation) {
512
550
  super(pos, vector3(0, 0, rotation), color);
513
551
  const vectors = vertices.map((vert) => vert.getPos());
552
+ const prevColor = this.getColor();
514
553
  this.shader = vertexColorShader;
515
554
  this.geometry = new PolygonGeometry(vectors);
516
555
  this.material = new VertexColorMaterial();
517
- if (color)
518
- this.material.setColor(color);
556
+ this.material.setColor(prevColor);
519
557
  const colors = vertices.map((vert) => vert.getColor() ?? this.material.getColor());
520
558
  this.material.setVertexColors(colors);
521
559
  }
@@ -592,7 +630,6 @@ export class Line3d extends SimulationElement3d {
592
630
  super(pos.getPos(), vector3(), to.getColor() ?? undefined);
593
631
  this.thickness = thickness;
594
632
  this.to = to.getPos();
595
- vec3.scale(this.to, devicePixelRatio, this.to);
596
633
  vec3.sub(this.to, this.pos, this.to);
597
634
  this.geometry = new Line3dGeometry(this.pos, this.to, this.thickness);
598
635
  }
@@ -621,7 +658,7 @@ export class Line2d extends SimulationElement2d {
621
658
  thickness;
622
659
  constructor(from, to, thickness = 1) {
623
660
  super(vector2FromVector3(from.getPos()), vector3(), from.getColor() ?? undefined);
624
- this.thickness = thickness * devicePixelRatio;
661
+ this.thickness = thickness;
625
662
  this.to = to.getPos();
626
663
  vec2.sub(this.to, this.pos, this.to);
627
664
  this.geometry = new Line2dGeometry(this.pos, this.to, this.thickness);
@@ -631,8 +668,6 @@ export class Line2d extends SimulationElement2d {
631
668
  }
632
669
  setEnd(pos, t = 0, f) {
633
670
  const tempPos = cloneBuf(pos);
634
- vector3ToPixelRatio(tempPos);
635
- // vec2.sub(tempPos, this.getPos(), tempPos);
636
671
  const diff = vector3();
637
672
  vec2.sub(tempPos, this.to, diff);
638
673
  return internalTransitionValues((p) => {
@@ -660,7 +695,6 @@ export class Cube extends SimulationElement3d {
660
695
  this.geometry = new CubeGeometry(this.width, this.height, this.depth);
661
696
  }
662
697
  setWidth(width, t = 0, f) {
663
- width *= devicePixelRatio;
664
698
  const diff = width - this.width;
665
699
  return internalTransitionValues((p) => {
666
700
  this.width += diff * p;
@@ -673,7 +707,6 @@ export class Cube extends SimulationElement3d {
673
707
  }, t, f);
674
708
  }
675
709
  setHeight(height, t = 0, f) {
676
- height *= devicePixelRatio;
677
710
  const diff = height - this.width;
678
711
  return internalTransitionValues((p) => {
679
712
  this.height += diff * p;
@@ -686,7 +719,6 @@ export class Cube extends SimulationElement3d {
686
719
  }, t, f);
687
720
  }
688
721
  setDepth(depth, t = 0, f) {
689
- depth *= devicePixelRatio;
690
722
  const diff = depth - this.width;
691
723
  return internalTransitionValues((p) => {
692
724
  this.depth += diff * p;
@@ -872,17 +904,17 @@ export class Spline2d extends SimulationElement2d {
872
904
  interpolateStart;
873
905
  interpolateLimit;
874
906
  length;
875
- constructor(pos, points, thickness = devicePixelRatio, detail = 40) {
907
+ constructor(pos, points, thickness = 1, detail = 40) {
876
908
  const tempPos = vector2FromVector3(pos.getPos());
877
909
  super(tempPos, vector3(), pos.getColor() ?? undefined);
878
- this.thickness = thickness * devicePixelRatio;
910
+ this.thickness = thickness;
879
911
  this.detail = detail;
880
912
  this.interpolateStart = 0;
881
913
  this.interpolateLimit = 1;
882
914
  this.length = 0;
883
915
  this.geometry = new Spline2dGeometry(points, this.thickness, this.detail);
884
916
  this.material = new VertexColorMaterial();
885
- this.material.setColor(pos.getColor() ?? color());
917
+ this.material.setColor(pos.getColor() ?? globalInfo.getDefaultColor());
886
918
  this.setVertexColors();
887
919
  this.shader = vertexColorShader;
888
920
  this.estimateLength();
@@ -974,7 +1006,6 @@ export class Spline2d extends SimulationElement2d {
974
1006
  this.vertexCache.updated();
975
1007
  }
976
1008
  setThickness(thickness, t = 0, f) {
977
- thickness *= devicePixelRatio;
978
1009
  const diff = thickness - this.thickness;
979
1010
  return internalTransitionValues((p) => {
980
1011
  this.thickness += diff * p;
@@ -1068,7 +1099,6 @@ export class Instance extends SimulationElement3d {
1068
1099
  const device = globalInfo.getDevice();
1069
1100
  if (!device)
1070
1101
  return;
1071
- // this.allocBuffer(size);
1072
1102
  const gpuBuffer = this.matrixBuffer.getBuffer();
1073
1103
  const buf = new Float32Array(transformation);
1074
1104
  device.queue.writeBuffer(gpuBuffer, instance * mat4ByteLength, buf.buffer, buf.byteOffset, buf.byteLength);
@@ -1099,8 +1129,8 @@ export class Instance extends SimulationElement3d {
1099
1129
  }
1100
1130
  return this.matrixBuffer.getBuffer();
1101
1131
  }
1102
- getVertexCount() {
1103
- return this.obj.getVertexCount();
1132
+ getTreeVertexCount() {
1133
+ return this.obj.getTreeVertexCount();
1104
1134
  }
1105
1135
  getIndexCount() {
1106
1136
  return this.obj.getIndexCount();
@@ -1,5 +1,5 @@
1
1
  /// <reference types="@webgpu/types" />
2
- import { Mat4, Vector2, Vector3 } from './types.js';
2
+ import { Mat4, Vector3 } from './types.js';
3
3
  import { Shader } from './shaders.js';
4
4
  import { SimulationElement3d } from './graphics.js';
5
5
  export declare class Float32ArrayCache {
@@ -29,8 +29,6 @@ export declare const buildMultisampleTexture: (device: GPUDevice, ctx: GPUCanvas
29
29
  export declare function lossyTriangulate<T>(vertices: T[]): (readonly [T, T, T])[];
30
30
  export declare function lossyTriangulateStrip<T>(vertices: T[]): T[];
31
31
  export declare function createIndexArray(length: number): number[];
32
- export declare function vector3ToPixelRatio(vec: Vector3): void;
33
- export declare function vector2ToPixelRatio(vec: Vector2): void;
34
32
  export declare function triangulateWireFrameOrder(len: number): number[];
35
33
  export declare function getVertexAndIndexSize(scene: SimulationElement3d[]): readonly [number, number];
36
34
  export declare function internalTransitionValues(onFrame: (deltaT: number, t: number, total: number) => void, adjustment: () => void, transitionLength: number, func?: (n: number) => number): Promise<void>;
@@ -141,15 +141,6 @@ export function createIndexArray(length) {
141
141
  .fill(0)
142
142
  .map((_, index) => index);
143
143
  }
144
- export function vector3ToPixelRatio(vec) {
145
- vec[0] *= devicePixelRatio;
146
- vec[1] *= devicePixelRatio;
147
- vec[2] *= devicePixelRatio;
148
- }
149
- export function vector2ToPixelRatio(vec) {
150
- vec[0] *= devicePixelRatio;
151
- vec[1] *= devicePixelRatio;
152
- }
153
144
  export function triangulateWireFrameOrder(len) {
154
145
  const order = Array(len)
155
146
  .fill(0)
@@ -168,7 +159,7 @@ export function getVertexAndIndexSize(scene) {
168
159
  let indexSize = 0;
169
160
  for (let i = 0; i < scene.length; i++) {
170
161
  const obj = scene[i];
171
- vertexSize += obj.getVertexCount() * obj.getShader().getBufferLength();
162
+ vertexSize += obj.getTreeVertexCount() * obj.getShader().getBufferLength();
172
163
  indexSize += obj.getIndexCount();
173
164
  }
174
165
  return [vertexSize, indexSize];
@@ -0,0 +1,5 @@
1
+ /// <reference types="@webgpu/types" />
2
+ import { SimulationElement3d } from './graphics.js';
3
+ import { Shader } from './shaders.js';
4
+ export declare function createBindGroup(shader: Shader, bindGroupIndex: number, buffers: GPUBuffer[]): GPUBindGroup;
5
+ export declare function writeUniformWorldMatrix(el: SimulationElement3d): void;
@@ -0,0 +1,22 @@
1
+ import { worldProjMatOffset } from './constants.js';
2
+ import { globalInfo } from './globals.js';
3
+ import { orthogonalMatrix, worldProjectionMatrix } from './simulation.js';
4
+ export function createBindGroup(shader, bindGroupIndex, buffers) {
5
+ const device = globalInfo.errorGetDevice();
6
+ const layout = shader.getBindGroupLayouts()[bindGroupIndex];
7
+ return device.createBindGroup({
8
+ layout: layout,
9
+ entries: buffers.map((buffer, index) => ({
10
+ binding: index,
11
+ resource: {
12
+ buffer
13
+ }
14
+ }))
15
+ });
16
+ }
17
+ export function writeUniformWorldMatrix(el) {
18
+ const device = globalInfo.errorGetDevice();
19
+ const uniformBuffer = el.getUniformBuffer();
20
+ const projBuf = el.is3d ? worldProjectionMatrix : orthogonalMatrix;
21
+ device.queue.writeBuffer(uniformBuffer, worldProjMatOffset, projBuf.buffer, projBuf.byteOffset, projBuf.byteLength);
22
+ }
@@ -50,6 +50,8 @@ export declare class Simulation extends Settings {
50
50
  start(): void;
51
51
  stop(): void;
52
52
  setBackground(color: Color): void;
53
+ setDefaultColor(color: Color): void;
54
+ getDefaultColor(): Color;
53
55
  getScene(): SimulationElement3d[];
54
56
  private render;
55
57
  private renderScene;
@@ -167,10 +167,11 @@ export class Simulation extends Settings {
167
167
  }
168
168
  else
169
169
  throw logger.error(`Canvas ref/id provided is invalid`);
170
- const parent = this.canvasRef.parentElement;
170
+ globalInfo.setCanvas(this);
171
171
  if (sceneCamera) {
172
172
  camera = sceneCamera;
173
173
  }
174
+ const parent = this.canvasRef.parentElement;
174
175
  if (parent === null)
175
176
  throw logger.error('Canvas parent is null');
176
177
  this.resizeEvents = [];
@@ -199,10 +200,10 @@ export class Simulation extends Settings {
199
200
  this.resizeEvents.push(cb);
200
201
  }
201
202
  getWidth() {
202
- return (this.canvasRef?.width || 0) / devicePixelRatio;
203
+ return this.canvasRef?.width || 0;
203
204
  }
204
205
  getHeight() {
205
- return (this.canvasRef?.height || 0) / devicePixelRatio;
206
+ return this.canvasRef?.height || 0;
206
207
  }
207
208
  add(el, id) {
208
209
  addToScene(this.scene, el, id);
@@ -265,6 +266,12 @@ export class Simulation extends Settings {
265
266
  setBackground(color) {
266
267
  this.bgColor = color;
267
268
  }
269
+ setDefaultColor(color) {
270
+ globalInfo.setDefaultColor(color);
271
+ }
272
+ getDefaultColor() {
273
+ return globalInfo.getDefaultColor();
274
+ }
268
275
  getScene() {
269
276
  return this.scene;
270
277
  }
package/dist/utils.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  /// <reference types="@webgpu/types" />
2
2
  import { SimulationElement3d, SplinePoint2d } from './graphics.js';
3
- import { FloatArray, Mat4, Vector2, Vector2m, Vector3, Vector3m, Vector4 } from './types.js';
3
+ import { FloatArray, LerpFunc, Mat4, Vector2, Vector2m, Vector3, Vector3m, Vector4 } from './types.js';
4
4
  import { Shader } from './shaders.js';
5
5
  export declare class Color {
6
6
  r: number;
@@ -81,6 +81,10 @@ export declare function waitFor(t: number): Promise<unknown>;
81
81
  export declare function distance2d(vector1: Vector2m, vector2: Vector2m): number;
82
82
  export declare function distance3d(vector1: Vector3m, vector2: Vector3m): number;
83
83
  export declare function interpolateColors(colors: Color[], t: number): Color;
84
+ export declare function vectorsToVertex(vectors: Vector3[]): Vertex[];
85
+ export declare function cloneVectors(vectors: Vector3[]): Vector3[];
84
86
  export declare function createBindGroup(shader: Shader, bindGroupIndex: number, buffers: GPUBuffer[]): GPUBindGroup;
85
87
  export declare function writeUniformWorldMatrix(el: SimulationElement3d): void;
88
+ export declare function transform(from: SimulationElement3d, to: SimulationElement3d, t: number, f?: LerpFunc): Promise<void>;
89
+ export declare function defaultColor(): Color;
86
90
  export {};
package/dist/utils.js CHANGED
@@ -233,16 +233,11 @@ export function colorf(val, a) {
233
233
  return color(val, val, val, a);
234
234
  }
235
235
  export function splinePoint2d(end, control1, control2, detail) {
236
- vec2.scale(control1, devicePixelRatio, control1);
237
- vec2.scale(control2, devicePixelRatio, control2);
238
- vec2.scale(end.getPos(), devicePixelRatio, end.getPos());
239
236
  const rawControls = [cloneBuf(control1), cloneBuf(control2)];
240
237
  vec2.add(end.getPos(), control2, control2);
241
238
  return new SplinePoint2d(null, end, control1, control2, rawControls, detail);
242
239
  }
243
240
  export function continuousSplinePoint2d(end, control, detail) {
244
- vec2.scale(control, devicePixelRatio, control);
245
- vec2.scale(end.getPos(), devicePixelRatio, end.getPos());
246
241
  const rawControls = [vector2(), cloneBuf(control)];
247
242
  vec2.add(end.getPos(), control, control);
248
243
  return new SplinePoint2d(null, end, null, control, rawControls, detail);
@@ -286,6 +281,12 @@ export function interpolateColors(colors, t) {
286
281
  res.a += diff.a;
287
282
  return res;
288
283
  }
284
+ export function vectorsToVertex(vectors) {
285
+ return vectors.map((vec) => vertex(...vec));
286
+ }
287
+ export function cloneVectors(vectors) {
288
+ return vectors.map((vec) => cloneBuf(vec));
289
+ }
289
290
  export function createBindGroup(shader, bindGroupIndex, buffers) {
290
291
  const device = globalInfo.errorGetDevice();
291
292
  const layout = shader.getBindGroupLayouts()[bindGroupIndex];
@@ -305,3 +306,29 @@ export function writeUniformWorldMatrix(el) {
305
306
  const projBuf = el.is3d ? worldProjectionMatrix : orthogonalMatrix;
306
307
  device.queue.writeBuffer(uniformBuffer, worldProjMatOffset, projBuf.buffer, projBuf.byteOffset, projBuf.byteLength);
307
308
  }
309
+ /// may have unexpected position behavior for nested elements, or elements with a geometry with a set triangle order
310
+ export function transform(from, to, t, f) {
311
+ const canvas = globalInfo.errorGetCanvas();
312
+ const fromVertCount = from.getVertexCount();
313
+ const toVertCount = to.getVertexCount();
314
+ if (fromVertCount < toVertCount) {
315
+ from.subDivideTo(toVertCount);
316
+ }
317
+ else if (fromVertCount > toVertCount) {
318
+ to.subDivideTo(fromVertCount);
319
+ }
320
+ canvas.remove(from);
321
+ canvas.add(to);
322
+ const fromVerts = from.getVertices();
323
+ return (async () => {
324
+ const prevPos = to.getPos();
325
+ to.moveTo(from.getPos());
326
+ to.moveTo(prevPos, t, f);
327
+ await to.animateVerticesFrom(fromVerts, t, f);
328
+ from.clearSubdivisions();
329
+ to.clearSubdivisions();
330
+ })();
331
+ }
332
+ export function defaultColor() {
333
+ return globalInfo.getDefaultColor();
334
+ }
package/package.json CHANGED
@@ -5,7 +5,7 @@
5
5
  "types": "./dist/index.d.ts",
6
6
  "author": "Jackson Otto",
7
7
  "description": "A simple graphics library using WebGPU",
8
- "version": "0.8.4",
8
+ "version": "0.10.1",
9
9
  "exports": {
10
10
  ".": {
11
11
  "import": "./dist/index.js",