simulationjsv2 0.9.0 → 0.10.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/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,7 +216,7 @@ 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
221
  vector3(-this.params.width / 2, this.params.height / 2),
114
222
  vector3(this.params.width / 2, this.params.height / 2),
@@ -118,51 +226,50 @@ export class SquareGeometry extends Geometry {
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,14 +406,14 @@ 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
419
  vec2.scale(normal, this.params.thickness, normal);
@@ -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';
@@ -41,6 +41,11 @@ export declare abstract class SimulationElement3d {
41
41
  getParent(): SimulationElement3d | null;
42
42
  getCullMode(): GPUCullMode;
43
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;
44
49
  setCenterOffset(offset: Vector3): void;
45
50
  getShader(): Shader;
46
51
  setShader(shader: Shader): void;
@@ -59,6 +64,8 @@ export declare abstract class SimulationElement3d {
59
64
  setWireframe(wireframe: boolean): void;
60
65
  isWireframe(): boolean;
61
66
  getMaterial(): Material;
67
+ getGeometry(): Geometry<object>;
68
+ getVertices(): Vector3[];
62
69
  getRelativePos(): Vector3;
63
70
  getPos(): Vector3;
64
71
  getRotation(): Vector3;
@@ -69,7 +76,9 @@ export declare abstract class SimulationElement3d {
69
76
  rotateChildren(angle: Vector3): void;
70
77
  rotate(amount: Vector3, t?: number, f?: LerpFunc): Promise<void>;
71
78
  rotateTo(rot: Vector3, t?: number, f?: LerpFunc): Promise<void>;
79
+ animateVerticesFrom(vertices: Vector3[], t: number, f?: LerpFunc): Promise<void>;
72
80
  getVertexCount(): number;
81
+ getTreeVertexCount(): number;
73
82
  getIndexCount(): number;
74
83
  writeBuffers(): void;
75
84
  getVertexBuffer(): Float32Array;
@@ -114,12 +123,14 @@ export declare class Square extends SimulationElement2d {
114
123
  }
115
124
  export declare class Circle extends SimulationElement2d {
116
125
  protected geometry: CircleGeometry;
117
- private radius;
118
- private detail;
119
126
  constructor(pos: Vector2, radius: number, color?: Color, detail?: number);
127
+ setDetail(detail: number): void;
120
128
  setRadius(num: number, t?: number, f?: LerpFunc): Promise<void>;
121
129
  scale(amount: number, t?: number, f?: LerpFunc): Promise<void>;
122
130
  }
131
+ export declare class OutlineCircle extends Circle {
132
+ constructor(pos: Vector2, radius: number, color?: Color, detail?: number);
133
+ }
123
134
  export declare class Polygon extends SimulationElement2d {
124
135
  protected geometry: PolygonGeometry;
125
136
  constructor(pos: Vector2, vertices: Vertex[], color?: Color, rotation?: number);
@@ -224,7 +235,7 @@ export declare class Instance<T extends SimulationElement3d> extends SimulationE
224
235
  getInstances(): Mat4[];
225
236
  getNumInstances(): number;
226
237
  getInstanceBuffer(): GPUBuffer;
227
- getVertexCount(): number;
238
+ getTreeVertexCount(): number;
228
239
  getIndexCount(): number;
229
240
  getGeometryTopology(): "list" | "strip";
230
241
  getVertexBuffer(): Float32Array;
package/dist/graphics.js CHANGED
@@ -1,6 +1,6 @@
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';
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
4
  import { Float32ArrayCache, internalTransitionValues, posTo2dScreen } from './internalUtils.js';
5
5
  import { mat4ByteLength, modelProjMatOffset } from './constants.js';
6
6
  import { MemoBuffer } from './buffers.js';
@@ -27,7 +27,7 @@ export class SimulationElement3d {
27
27
  isInstanced = false;
28
28
  is3d = true;
29
29
  isEmpty = false;
30
- constructor(pos, rotation, color = new Color()) {
30
+ constructor(pos, rotation, color = globalInfo.getDefaultColor()) {
31
31
  this.pos = pos;
32
32
  this.centerOffset = vector3();
33
33
  this.vertexCache = new Float32ArrayCache();
@@ -41,7 +41,7 @@ export class SimulationElement3d {
41
41
  this.prevInfo = null;
42
42
  this.shader = defaultShader;
43
43
  this.material = new BasicMaterial(color);
44
- this.cullMode = 'back';
44
+ this.cullMode = 'none';
45
45
  this.id = null;
46
46
  }
47
47
  getId() {
@@ -99,6 +99,32 @@ export class SimulationElement3d {
99
99
  setCullMode(mode) {
100
100
  this.cullMode = mode;
101
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
+ }
102
128
  setCenterOffset(offset) {
103
129
  this.centerOffset = offset;
104
130
  }
@@ -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
  }
@@ -289,13 +321,22 @@ export class SimulationElement3d {
289
321
  this.rotation = cloneBuf(rot);
290
322
  }, t, f);
291
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
+ }
292
330
  getVertexCount() {
331
+ return this.getVertices().length;
332
+ }
333
+ getTreeVertexCount() {
293
334
  if (this.vertexCache.shouldUpdate()) {
294
- this.geometry.recompute();
335
+ this.geometry.compute();
295
336
  }
296
337
  let vertexCount = this.geometry.getIndexes(this.isWireframe()).length;
297
338
  for (let i = 0; i < this.children.length; i++) {
298
- vertexCount += this.children[i].getVertexCount();
339
+ vertexCount += this.children[i].getTreeVertexCount();
299
340
  }
300
341
  return vertexCount;
301
342
  }
@@ -310,8 +351,8 @@ export class SimulationElement3d {
310
351
  this.shader.writeBuffers(this);
311
352
  }
312
353
  getVertexBuffer() {
313
- if (this.vertexCache.shouldUpdate()) {
314
- this.geometry.recompute();
354
+ if (this.vertexCache.shouldUpdate() || this.geometry.hasUpdated()) {
355
+ this.geometry.compute();
315
356
  const vertices = this.geometry.getVertices();
316
357
  const stride = this.shader.getBufferLength();
317
358
  const vertexBuffer = new Float32Array(vertices.length * stride);
@@ -363,8 +404,7 @@ export class Plane extends SimulationElement3d {
363
404
  super(pos, rotation, color);
364
405
  this.rotation = rotation;
365
406
  this.points = points;
366
- this.geometry = new PlaneGeometry(points);
367
- this.cullMode = 'none';
407
+ this.geometry = new PlaneGeometry(points.map((vert) => vert.getPos()));
368
408
  }
369
409
  setPoints(newPoints) {
370
410
  this.points = newPoints;
@@ -463,50 +503,57 @@ export class Square extends SimulationElement2d {
463
503
  }
464
504
  export class Circle extends SimulationElement2d {
465
505
  geometry;
466
- radius;
467
- detail;
468
506
  constructor(pos, radius, color, detail = 50) {
469
507
  super(pos, vector3(), color);
470
- this.radius = radius;
471
- this.detail = detail;
472
- this.geometry = new CircleGeometry(this.radius, this.detail);
508
+ this.geometry = new CircleGeometry(radius, detail);
509
+ }
510
+ setDetail(detail) {
511
+ this.geometry.setDetail(detail);
473
512
  }
474
513
  setRadius(num, t = 0, f) {
475
- const diff = num - this.radius;
514
+ let radius = this.geometry.getRadius();
515
+ const diff = num - radius;
476
516
  return internalTransitionValues((p) => {
477
- this.radius += diff * p;
478
- this.geometry.setRadius(this.radius);
517
+ radius += diff * p;
518
+ this.geometry.setRadius(radius);
479
519
  this.vertexCache.updated();
480
520
  }, () => {
481
- this.radius = num;
482
- this.geometry.setRadius(this.radius);
521
+ radius = num;
522
+ this.geometry.setRadius(radius);
483
523
  this.vertexCache.updated();
484
524
  }, t, f);
485
525
  }
486
526
  scale(amount, t = 0, f) {
487
- const finalRadius = this.radius * amount;
488
- const diff = finalRadius - this.radius;
527
+ let radius = this.geometry.getRadius();
528
+ const finalRadius = radius * amount;
529
+ const diff = finalRadius - radius;
489
530
  return internalTransitionValues((p) => {
490
- this.radius += diff * p;
491
- this.geometry.setRadius(this.radius);
531
+ radius += diff * p;
532
+ this.geometry.setRadius(radius);
492
533
  this.vertexCache.updated();
493
534
  }, () => {
494
- this.radius = finalRadius;
495
- this.geometry.setRadius(this.radius);
535
+ radius = finalRadius;
536
+ this.geometry.setRadius(radius);
496
537
  this.vertexCache.updated();
497
538
  }, t, f);
498
539
  }
499
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
+ }
500
547
  export class Polygon extends SimulationElement2d {
501
548
  geometry;
502
549
  constructor(pos, vertices, color, rotation) {
503
550
  super(pos, vector3(0, 0, rotation), color);
504
551
  const vectors = vertices.map((vert) => vert.getPos());
552
+ const prevColor = this.getColor();
505
553
  this.shader = vertexColorShader;
506
554
  this.geometry = new PolygonGeometry(vectors);
507
555
  this.material = new VertexColorMaterial();
508
- if (color)
509
- this.material.setColor(color);
556
+ this.material.setColor(prevColor);
510
557
  const colors = vertices.map((vert) => vert.getColor() ?? this.material.getColor());
511
558
  this.material.setVertexColors(colors);
512
559
  }
@@ -867,7 +914,7 @@ export class Spline2d extends SimulationElement2d {
867
914
  this.length = 0;
868
915
  this.geometry = new Spline2dGeometry(points, this.thickness, this.detail);
869
916
  this.material = new VertexColorMaterial();
870
- this.material.setColor(pos.getColor() ?? color());
917
+ this.material.setColor(pos.getColor() ?? globalInfo.getDefaultColor());
871
918
  this.setVertexColors();
872
919
  this.shader = vertexColorShader;
873
920
  this.estimateLength();
@@ -1082,8 +1129,8 @@ export class Instance extends SimulationElement3d {
1082
1129
  }
1083
1130
  return this.matrixBuffer.getBuffer();
1084
1131
  }
1085
- getVertexCount() {
1086
- return this.obj.getVertexCount();
1132
+ getTreeVertexCount() {
1133
+ return this.obj.getTreeVertexCount();
1087
1134
  }
1088
1135
  getIndexCount() {
1089
1136
  return this.obj.getIndexCount();
@@ -159,7 +159,7 @@ export function getVertexAndIndexSize(scene) {
159
159
  let indexSize = 0;
160
160
  for (let i = 0; i < scene.length; i++) {
161
161
  const obj = scene[i];
162
- vertexSize += obj.getVertexCount() * obj.getShader().getBufferLength();
162
+ vertexSize += obj.getTreeVertexCount() * obj.getShader().getBufferLength();
163
163
  indexSize += obj.getIndexCount();
164
164
  }
165
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 = [];
@@ -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
@@ -281,6 +281,12 @@ export function interpolateColors(colors, t) {
281
281
  res.a += diff.a;
282
282
  return res;
283
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
+ }
284
290
  export function createBindGroup(shader, bindGroupIndex, buffers) {
285
291
  const device = globalInfo.errorGetDevice();
286
292
  const layout = shader.getBindGroupLayouts()[bindGroupIndex];
@@ -300,3 +306,29 @@ export function writeUniformWorldMatrix(el) {
300
306
  const projBuf = el.is3d ? worldProjectionMatrix : orthogonalMatrix;
301
307
  device.queue.writeBuffer(uniformBuffer, worldProjMatOffset, projBuf.buffer, projBuf.byteOffset, projBuf.byteLength);
302
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.9.0",
8
+ "version": "0.10.2",
9
9
  "exports": {
10
10
  ".": {
11
11
  "import": "./dist/index.js",