simulationjsv2 0.2.2 → 0.2.4

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.
@@ -1 +1 @@
1
- export declare const BUF_LEN = 11;
1
+ export declare const BUF_LEN = 10;
package/dist/constants.js CHANGED
@@ -1 +1 @@
1
- export const BUF_LEN = 11;
1
+ export const BUF_LEN = 10;
@@ -6,7 +6,8 @@ export declare abstract class SimulationElement<T extends Vector2 | Vector3 = Ve
6
6
  private color;
7
7
  camera: Camera | null;
8
8
  vertexCache: VertexCache;
9
- constructor(pos: T, color?: Color);
9
+ is3d: boolean;
10
+ constructor(pos: T, color?: Color, is3d?: boolean);
10
11
  setPos(pos: T): void;
11
12
  getPos(): T;
12
13
  setCamera(camera: Camera): void;
@@ -16,19 +17,36 @@ export declare abstract class SimulationElement<T extends Vector2 | Vector3 = Ve
16
17
  moveTo(pos: T, t?: number, f?: LerpFunc): Promise<void>;
17
18
  abstract getBuffer(camera: Camera, force: boolean): number[];
18
19
  }
19
- export declare class Plane extends SimulationElement {
20
+ export declare abstract class SimulationElement3d extends SimulationElement {
21
+ rotation: Vector3;
22
+ private wireframe;
23
+ protected wireframeCache: VertexCache;
24
+ constructor(pos: Vector3, rotation?: Vector3, color?: Color);
25
+ setWireframe(wireframe: boolean): void;
26
+ isWireframe(): boolean;
27
+ rotate(amount: Vector3, t?: number, f?: LerpFunc): Promise<void>;
28
+ setRotation(rot: Vector3, t?: number, f?: LerpFunc): Promise<void>;
29
+ protected wireframeFromVertexOrder(vertices: Vector3[], order: number[]): number[];
30
+ abstract getWireframe(camera: Camera, force: boolean): number[];
31
+ abstract getTriangles(camera: Camera, force: boolean): number[];
32
+ getBuffer(camera: Camera, force: boolean): number[];
33
+ }
34
+ export declare abstract class SimulationElement2d extends SimulationElement<Vector2> {
35
+ rotation: number;
36
+ constructor(pos: Vector2, rotation?: number, color?: Color);
37
+ rotate(rotation: number, t?: number, f?: LerpFunc): Promise<void>;
38
+ setRotation(newRotation: number, t?: number, f?: LerpFunc): Promise<void>;
39
+ }
40
+ export declare class Plane extends SimulationElement3d {
20
41
  private points;
21
- private rotation;
22
42
  constructor(pos: Vector3, points: Vertex[], color?: Color, rotation?: Vector3);
23
43
  setPoints(newPoints: Vertex[]): void;
24
- rotate(amount: Vector3, t?: number, f?: LerpFunc): Promise<void>;
25
- rotateTo(angle: Vector3, t?: number, f?: LerpFunc): Promise<void>;
26
- getBuffer(_: Camera, force: boolean): number[];
44
+ getWireframe(_: Camera, force: boolean): number[];
45
+ getTriangles(_: Camera, force: boolean): number[];
27
46
  }
28
- export declare class Square extends SimulationElement<Vector2> {
47
+ export declare class Square extends SimulationElement2d {
29
48
  private width;
30
49
  private height;
31
- private rotation;
32
50
  private vertexColors;
33
51
  private points;
34
52
  /**
@@ -40,11 +58,9 @@ export declare class Square extends SimulationElement<Vector2> {
40
58
  scale(amount: number, t?: number, f?: LerpFunc): Promise<void>;
41
59
  setWidth(num: number, t?: number, f?: LerpFunc): Promise<void>;
42
60
  setHeight(num: number, t?: number, f?: LerpFunc): Promise<void>;
43
- rotate(rotation: number, t?: number, f?: LerpFunc): Promise<void>;
44
- setRotation(newRotation: number, t?: number, f?: LerpFunc): Promise<void>;
45
61
  getBuffer(camera: Camera, force: boolean): number[];
46
62
  }
47
- export declare class Circle extends SimulationElement<Vector2> {
63
+ export declare class Circle extends SimulationElement2d {
48
64
  private radius;
49
65
  private detail;
50
66
  constructor(pos: Vector2, radius: number, color?: Color, detail?: number);
@@ -52,24 +68,22 @@ export declare class Circle extends SimulationElement<Vector2> {
52
68
  scale(amount: number, t?: number, f?: LerpFunc): Promise<void>;
53
69
  getBuffer(camera: Camera, force: boolean): number[];
54
70
  }
55
- export declare class Polygon extends SimulationElement<Vector2> {
71
+ export declare class Polygon extends SimulationElement2d {
56
72
  private vertices;
57
- private rotation;
58
- constructor(pos: Vector2, vertices: Vertex[], color?: Color);
59
- rotate(amount: number, t?: number, f?: LerpFunc): Promise<void>;
60
- rotateTo(num: number, t?: number, f?: LerpFunc): Promise<void>;
73
+ constructor(pos: Vector2, vertices: Vertex[], color?: Color, rotation?: number);
61
74
  getVertices(): Vertex[];
62
75
  setVertices(newVertices: Vertex[], t?: number, f?: LerpFunc): Promise<void>;
63
76
  getBuffer(camera: Camera, force: boolean): number[];
64
77
  }
65
- export declare class Line3d extends SimulationElement {
78
+ export declare class Line3d extends SimulationElement3d {
66
79
  private to;
67
80
  private toColor;
68
81
  private thickness;
69
82
  constructor(pos: Vertex, to: Vertex, thickness: number);
70
83
  setStart(pos: Vector3, t?: number, f?: LerpFunc): Promise<void>;
71
84
  setEnd(pos: Vector3, t?: number, f?: LerpFunc): Promise<void>;
72
- getBuffer(_: Camera, force: boolean): number[];
85
+ getWireframe(_: Camera, force: boolean): number[];
86
+ getTriangles(_: Camera, force: boolean): number[];
73
87
  }
74
88
  export declare class Line2d extends SimulationElement {
75
89
  private to;
@@ -81,26 +95,22 @@ export declare class Line2d extends SimulationElement {
81
95
  setEnd(pos: Vector2, t?: number, f?: LerpFunc): Promise<void>;
82
96
  getBuffer(camera: Camera, force: boolean): number[];
83
97
  }
84
- export declare class Cube extends SimulationElement {
98
+ export declare class Cube extends SimulationElement3d {
85
99
  private vertices;
86
- private rotation;
87
100
  private width;
88
101
  private height;
89
102
  private depth;
90
- private wireframe;
91
103
  private wireframeLines;
92
104
  private static readonly wireframeOrder;
93
105
  constructor(pos: Vector3, width: number, height: number, depth: number, color?: Color, rotation?: Vector3);
94
106
  private computeVertices;
95
107
  private shiftWireframeLines;
96
- setWireframe(wireframe: boolean): void;
97
- rotate(amount: Vector3, t?: number, f?: LerpFunc): Promise<void>;
98
- setRotation(rot: Vector3, t?: number, f?: LerpFunc): Promise<void>;
99
108
  setWidth(width: number, t?: number, f?: LerpFunc): Promise<void>;
100
109
  setHeight(height: number, t?: number, f?: LerpFunc): Promise<void>;
101
110
  setDepth(depth: number, t?: number, f?: LerpFunc): Promise<void>;
102
111
  scale(amount: number, t?: number, f?: LerpFunc): Promise<void>;
103
- getBuffer(camera: Camera, force: boolean): number[];
112
+ getWireframe(_: Camera, force: boolean): number[];
113
+ getTriangles(_: Camera, force: boolean): number[];
104
114
  }
105
115
  export declare class BezierCurve2d {
106
116
  private points;
package/dist/graphics.js CHANGED
@@ -1,11 +1,12 @@
1
1
  import { vec3, quat, mat4, vec2, vec4 } from 'wgpu-matrix';
2
- import { Vertex, VertexCache, cloneBuf, color, colorFromVector4, lossyTriangulate, vec3ToPixelRatio, vector3FromVector2, vector2, vector3, vertex, vertexBuffer2d, vertexBuffer3d, Color, transitionValues, logger, vector2FromVector3, interpolateColors } from './utils.js';
2
+ import { Vertex, VertexCache, cloneBuf, color, colorFromVector4, lossyTriangulate, vec3ToPixelRatio, vector3FromVector2, vector2, vector3, vertex, vertexBuffer, Color, transitionValues, logger, vector2FromVector3, interpolateColors } from './utils.js';
3
3
  export class SimulationElement {
4
4
  pos;
5
5
  color;
6
6
  camera;
7
7
  vertexCache;
8
- constructor(pos, color = new Color()) {
8
+ is3d;
9
+ constructor(pos, color = new Color(), is3d = true) {
9
10
  this.pos = pos;
10
11
  const temp = vector3(...this.pos);
11
12
  vec3ToPixelRatio(temp);
@@ -15,6 +16,7 @@ export class SimulationElement {
15
16
  this.color = color;
16
17
  this.vertexCache = new VertexCache();
17
18
  this.camera = null;
19
+ this.is3d = is3d;
18
20
  }
19
21
  setPos(pos) {
20
22
  this.pos = pos;
@@ -71,44 +73,122 @@ export class SimulationElement {
71
73
  }, t, f);
72
74
  }
73
75
  }
74
- export class Plane extends SimulationElement {
75
- points;
76
+ export class SimulationElement3d extends SimulationElement {
76
77
  rotation;
77
- constructor(pos, points, color, rotation = vector3()) {
78
+ wireframe = false;
79
+ wireframeCache;
80
+ constructor(pos, rotation = vector3(), color) {
78
81
  super(pos, color);
79
- this.points = points;
80
82
  this.rotation = rotation;
83
+ this.wireframeCache = new VertexCache();
81
84
  }
82
- setPoints(newPoints) {
83
- this.points = newPoints;
85
+ setWireframe(wireframe) {
86
+ this.wireframe = wireframe;
87
+ }
88
+ isWireframe() {
89
+ return this.wireframe;
84
90
  }
85
91
  rotate(amount, t = 0, f) {
86
- const initial = vec3.clone(this.rotation);
92
+ const finalRotation = cloneBuf(this.rotation);
93
+ vec3.add(finalRotation, amount, finalRotation);
87
94
  return transitionValues((p) => {
88
- const step = vector3();
89
- vec3.scale(amount, p, step);
90
- vec3.add(this.rotation, step, this.rotation);
95
+ this.rotation[0] += amount[0] * p;
96
+ this.rotation[1] += amount[1] * p;
97
+ this.rotation[2] += amount[2] * p;
91
98
  this.vertexCache.updated();
92
99
  }, () => {
93
- vec3.add(initial, amount, initial);
94
- this.rotation = initial;
100
+ this.rotation = finalRotation;
95
101
  this.vertexCache.updated();
96
102
  }, t, f);
97
103
  }
98
- rotateTo(angle, t = 0, f) {
104
+ setRotation(rot, t = 0, f) {
99
105
  const diff = vector3();
100
- vec3.sub(angle, this.rotation, diff);
106
+ vec3.sub(rot, this.rotation, diff);
101
107
  return transitionValues((p) => {
102
- const toRotate = vector3();
103
- vec3.scale(diff, p, toRotate);
104
- vec3.add(this.rotation, toRotate, this.rotation);
108
+ this.rotation[0] += diff[0] * p;
109
+ this.rotation[1] += diff[1] * p;
110
+ this.rotation[2] += diff[2] * p;
105
111
  this.vertexCache.updated();
106
112
  }, () => {
107
- this.rotation = angle;
113
+ this.rotation = rot;
108
114
  this.vertexCache.updated();
109
115
  }, t, f);
110
116
  }
111
- getBuffer(_, force) {
117
+ wireframeFromVertexOrder(vertices, order) {
118
+ let rotMatrix = mat4.identity();
119
+ mat4.rotateZ(rotMatrix, this.rotation[2], rotMatrix);
120
+ mat4.rotateY(rotMatrix, this.rotation[1], rotMatrix);
121
+ mat4.rotateX(rotMatrix, this.rotation[0], rotMatrix);
122
+ const pos = this.getPos();
123
+ return order
124
+ .map((vertexIndex) => {
125
+ const vertex = cloneBuf(vertices[vertexIndex]);
126
+ vec3.transformMat4(vertex, rotMatrix, vertex);
127
+ return vertexBuffer(vertex[0] + pos[0], vertex[1] + pos[1], vertex[2] + pos[2], this.getColor());
128
+ })
129
+ .flat();
130
+ }
131
+ getBuffer(camera, force) {
132
+ if (this.wireframe)
133
+ return this.getWireframe(camera, force);
134
+ return this.getTriangles(camera, force);
135
+ }
136
+ }
137
+ export class SimulationElement2d extends SimulationElement {
138
+ rotation;
139
+ constructor(pos, rotation = 0, color) {
140
+ super(pos, color, false);
141
+ this.rotation = rotation;
142
+ }
143
+ rotate(rotation, t = 0, f) {
144
+ const finalRotation = this.rotation + rotation;
145
+ return transitionValues((p) => {
146
+ this.rotation += rotation * p;
147
+ this.vertexCache.updated();
148
+ }, () => {
149
+ this.rotation = finalRotation;
150
+ this.vertexCache.updated();
151
+ }, t, f);
152
+ }
153
+ setRotation(newRotation, t = 0, f) {
154
+ const diff = newRotation - this.rotation;
155
+ return transitionValues((p) => {
156
+ this.rotation += diff * p;
157
+ this.vertexCache.updated();
158
+ }, () => {
159
+ this.rotation = newRotation;
160
+ this.vertexCache.updated();
161
+ }, t, f);
162
+ }
163
+ }
164
+ export class Plane extends SimulationElement3d {
165
+ points;
166
+ constructor(pos, points, color, rotation = vector3()) {
167
+ super(pos, rotation, color);
168
+ this.points = points;
169
+ this.rotation = rotation;
170
+ }
171
+ setPoints(newPoints) {
172
+ this.points = newPoints;
173
+ }
174
+ getWireframe(_, force) {
175
+ if (this.wireframeCache.shouldUpdate() || force) {
176
+ const order = Array(this.points.length)
177
+ .fill(0)
178
+ .map((_, index) => index);
179
+ let front = 0;
180
+ let back = this.points.length - 1;
181
+ while (front < back) {
182
+ order.push(front, back);
183
+ front++;
184
+ back--;
185
+ }
186
+ const vertices = this.points.map((p) => p.getPos());
187
+ return this.wireframeFromVertexOrder(vertices, order);
188
+ }
189
+ return this.wireframeCache.getCache();
190
+ }
191
+ getTriangles(_, force) {
112
192
  if (this.vertexCache.shouldUpdate() || force) {
113
193
  let resBuffer = [];
114
194
  const triangles = lossyTriangulate(this.points).flat();
@@ -122,7 +202,7 @@ export class Plane extends SimulationElement {
122
202
  vec3.add(out, this.getPos(), out);
123
203
  let vertexColor = verticy.getColor();
124
204
  vertexColor = vertexColor ? vertexColor : this.getColor();
125
- resBuffer = resBuffer.concat(vertexBuffer3d(out[0], out[1], out[2], vertexColor));
205
+ resBuffer = resBuffer.concat(vertexBuffer(out[0], out[1], out[2], vertexColor));
126
206
  });
127
207
  this.vertexCache.setCache(resBuffer);
128
208
  return resBuffer;
@@ -130,20 +210,18 @@ export class Plane extends SimulationElement {
130
210
  return this.vertexCache.getCache();
131
211
  }
132
212
  }
133
- export class Square extends SimulationElement {
213
+ export class Square extends SimulationElement2d {
134
214
  width;
135
215
  height;
136
- rotation;
137
216
  vertexColors;
138
217
  points;
139
218
  /**
140
219
  * @param vertexColors{Record<number, Color>} - 0 is top left vertex, numbers increase clockwise
141
220
  */
142
221
  constructor(pos, width, height, color, rotation, vertexColors) {
143
- super(pos, color);
222
+ super(pos, rotation, color);
144
223
  this.width = width * devicePixelRatio;
145
224
  this.height = height * devicePixelRatio;
146
- this.rotation = rotation || 0;
147
225
  this.vertexColors = vertexColors || {};
148
226
  this.points = [
149
227
  vector2(this.width / 2, this.height / 2),
@@ -211,29 +289,8 @@ export class Square extends SimulationElement {
211
289
  this.vertexCache.updated();
212
290
  }, t, f);
213
291
  }
214
- rotate(rotation, t = 0, f) {
215
- const finalRotation = this.rotation + rotation;
216
- return transitionValues((p) => {
217
- this.rotation += rotation * p;
218
- this.vertexCache.updated();
219
- }, () => {
220
- this.rotation = finalRotation;
221
- this.vertexCache.updated();
222
- }, t, f);
223
- }
224
- setRotation(newRotation, t = 0, f) {
225
- const diff = newRotation - this.rotation;
226
- return transitionValues((p) => {
227
- this.rotation += diff * p;
228
- this.vertexCache.updated();
229
- }, () => {
230
- this.rotation = newRotation;
231
- this.vertexCache.updated();
232
- }, t, f);
233
- }
234
292
  getBuffer(camera, force) {
235
293
  if (this.vertexCache.shouldUpdate() || force) {
236
- let resBuffer = [];
237
294
  const vertexOrder = [0, 1, 2, 0, 2, 3];
238
295
  const rotationMat = mat4.identity();
239
296
  mat4.rotateZ(rotationMat, this.rotation, rotationMat);
@@ -247,22 +304,24 @@ export class Square extends SimulationElement {
247
304
  pos[1] -= this.height / 2;
248
305
  return pos;
249
306
  });
250
- vertexOrder.forEach((vertex) => {
307
+ let resBuffer = vertexOrder
308
+ .map((vertex) => {
251
309
  let vertexColor = this.vertexColors[vertex];
252
310
  vertexColor = vertexColor ? vertexColor : this.getColor();
253
- resBuffer = resBuffer.concat(vertexBuffer2d(points[vertex][0], points[vertex][1], vertexColor));
254
- });
311
+ return vertexBuffer(points[vertex][0], points[vertex][1], 0, vertexColor);
312
+ })
313
+ .flat();
255
314
  this.vertexCache.setCache(resBuffer);
256
315
  return resBuffer;
257
316
  }
258
317
  return this.vertexCache.getCache();
259
318
  }
260
319
  }
261
- export class Circle extends SimulationElement {
320
+ export class Circle extends SimulationElement2d {
262
321
  radius;
263
- detail = 100;
322
+ detail;
264
323
  constructor(pos, radius, color, detail = 50) {
265
- super(pos, color);
324
+ super(pos, 0, color);
266
325
  this.radius = radius * devicePixelRatio;
267
326
  this.detail = detail;
268
327
  }
@@ -311,11 +370,10 @@ export class Circle extends SimulationElement {
311
370
  return this.vertexCache.getCache();
312
371
  }
313
372
  }
314
- export class Polygon extends SimulationElement {
373
+ export class Polygon extends SimulationElement2d {
315
374
  vertices;
316
- rotation = 0;
317
- constructor(pos, vertices, color) {
318
- super(pos, color);
375
+ constructor(pos, vertices, color, rotation) {
376
+ super(pos, rotation, color);
319
377
  this.vertices = vertices.map((vertex) => {
320
378
  const newVertex = vertex.clone();
321
379
  newVertex.setZ(0);
@@ -323,24 +381,6 @@ export class Polygon extends SimulationElement {
323
381
  return vertex;
324
382
  });
325
383
  }
326
- rotate(amount, t = 0, f) {
327
- const finalRotation = this.rotation + amount;
328
- return transitionValues((p) => {
329
- this.rotation += amount * p;
330
- this.vertexCache.updated();
331
- }, () => {
332
- this.rotation = finalRotation;
333
- }, t, f);
334
- }
335
- rotateTo(num, t = 0, f) {
336
- const diff = num - this.rotation;
337
- return transitionValues((p) => {
338
- this.rotation += diff * p;
339
- this.vertexCache.updated();
340
- }, () => {
341
- this.rotation = num;
342
- }, t, f);
343
- }
344
384
  getVertices() {
345
385
  return this.vertices;
346
386
  }
@@ -424,7 +464,7 @@ export class Polygon extends SimulationElement {
424
464
  vec3.transformMat4(pos, rotationMat, pos);
425
465
  vec3.add(this.getPos(), pos, pos);
426
466
  pos[1] = camera.getScreenSize()[1] - pos[1];
427
- resBuffer = resBuffer.concat(vertexBuffer2d(pos[0], pos[1], vert.getColor() || this.getColor()));
467
+ resBuffer = resBuffer.concat(vertexBuffer(pos[0], pos[1], 0, vert.getColor() || this.getColor()));
428
468
  });
429
469
  this.vertexCache.setCache(resBuffer);
430
470
  return resBuffer;
@@ -432,12 +472,12 @@ export class Polygon extends SimulationElement {
432
472
  return this.vertexCache.getCache();
433
473
  }
434
474
  }
435
- export class Line3d extends SimulationElement {
475
+ export class Line3d extends SimulationElement3d {
436
476
  to;
437
477
  toColor;
438
478
  thickness;
439
479
  constructor(pos, to, thickness) {
440
- super(pos.getPos(), to.getColor() || undefined);
480
+ super(pos.getPos(), vector3(), to.getColor() || undefined);
441
481
  this.thickness = thickness;
442
482
  this.toColor = to.getColor() || this.getColor();
443
483
  this.to = to.getPos();
@@ -462,19 +502,35 @@ export class Line3d extends SimulationElement {
462
502
  this.vertexCache.updated();
463
503
  }, t, f);
464
504
  }
465
- getBuffer(_, force) {
505
+ getWireframe(_, force) {
506
+ if (this.wireframeCache.shouldUpdate() || force) {
507
+ const normal = vector2(-this.to[1], this.to[0]);
508
+ vec2.normalize(normal, normal);
509
+ vec2.scale(normal, this.thickness / 2, normal);
510
+ const vertices = [
511
+ vector3(normal[0], normal[1]),
512
+ vector3(-normal[0], -normal[1]),
513
+ vector3(this.to[0] + normal[0], this.to[1] + normal[1], this.to[2]),
514
+ vector3(this.to[0] - normal[0], this.to[1] - normal[1], this.to[2])
515
+ ];
516
+ const order = [0, 1, 3, 2, 0, 3];
517
+ return this.wireframeFromVertexOrder(vertices, order);
518
+ }
519
+ return this.wireframeCache.getCache();
520
+ }
521
+ getTriangles(_, force) {
466
522
  if (this.vertexCache.shouldUpdate() || force) {
467
523
  const normal = vector2(-this.to[1], this.to[0]);
468
524
  vec2.normalize(normal, normal);
469
525
  vec2.scale(normal, this.thickness / 2, normal);
470
526
  const pos = this.getPos();
471
527
  const resBuffer = [
472
- ...vertexBuffer3d(pos[0] + normal[0], pos[1] + normal[1], pos[2], this.getColor()),
473
- ...vertexBuffer3d(pos[0] - normal[0], pos[1] - normal[1], pos[2], this.getColor()),
474
- ...vertexBuffer3d(pos[0] + this.to[0] + normal[0], pos[1] + this.to[1] + normal[1], pos[2] + this.to[2], this.toColor || this.getColor()),
475
- ...vertexBuffer3d(pos[0] - normal[0], pos[1] - normal[1], pos[2], this.getColor()),
476
- ...vertexBuffer3d(pos[0] + this.to[0] + normal[0], pos[1] + this.to[1] + normal[1], pos[2] + this.to[2], this.toColor || this.getColor()),
477
- ...vertexBuffer3d(pos[0] + this.to[0] - normal[0], pos[1] + this.to[1] - normal[1], pos[2] + this.to[2], this.toColor || this.getColor())
528
+ ...vertexBuffer(pos[0] + normal[0], pos[1] + normal[1], pos[2], this.getColor()),
529
+ ...vertexBuffer(pos[0] - normal[0], pos[1] - normal[1], pos[2], this.getColor()),
530
+ ...vertexBuffer(pos[0] + this.to[0] + normal[0], pos[1] + this.to[1] + normal[1], pos[2] + this.to[2], this.toColor || this.getColor()),
531
+ ...vertexBuffer(pos[0] - normal[0], pos[1] - normal[1], pos[2], this.getColor()),
532
+ ...vertexBuffer(pos[0] + this.to[0] + normal[0], pos[1] + this.to[1] + normal[1], pos[2] + this.to[2], this.toColor || this.getColor()),
533
+ ...vertexBuffer(pos[0] + this.to[0] - normal[0], pos[1] + this.to[1] - normal[1], pos[2] + this.to[2], this.toColor || this.getColor())
478
534
  ];
479
535
  this.vertexCache.setCache(resBuffer);
480
536
  return resBuffer;
@@ -534,12 +590,12 @@ export class Line2d extends SimulationElement {
534
590
  const screenSize = camera.getScreenSize();
535
591
  const pos = this.getPos();
536
592
  const resBuffer = [
537
- ...vertexBuffer2d(pos[0] + normal[0], screenSize[1] - pos[1] + normal[1], this.getColor()),
538
- ...vertexBuffer2d(pos[0] - normal[0], screenSize[1] - pos[1] - normal[1], this.getColor()),
539
- ...vertexBuffer2d(pos[0] + this.to[0] + normal[0], screenSize[1] - pos[1] + this.to[1] + normal[1], this.toColor || this.getColor()),
540
- ...vertexBuffer2d(pos[0] - normal[0], screenSize[1] - pos[1] - normal[1], this.getColor()),
541
- ...vertexBuffer2d(pos[0] + this.to[0] + normal[0], screenSize[1] - pos[1] + this.to[1] + normal[1], this.toColor || this.getColor()),
542
- ...vertexBuffer2d(pos[0] + this.to[0] - normal[0], screenSize[1] - pos[1] + this.to[1] - normal[1], this.toColor || this.getColor())
593
+ ...vertexBuffer(pos[0] + normal[0], screenSize[1] - pos[1] + normal[1], 0, this.getColor()),
594
+ ...vertexBuffer(pos[0] - normal[0], screenSize[1] - pos[1] - normal[1], 0, this.getColor()),
595
+ ...vertexBuffer(pos[0] + this.to[0] + normal[0], screenSize[1] - pos[1] + this.to[1] + normal[1], 0, this.toColor || this.getColor()),
596
+ ...vertexBuffer(pos[0] - normal[0], screenSize[1] - pos[1] - normal[1], 0, this.getColor()),
597
+ ...vertexBuffer(pos[0] + this.to[0] + normal[0], screenSize[1] - pos[1] + this.to[1] + normal[1], 0, this.toColor || this.getColor()),
598
+ ...vertexBuffer(pos[0] + this.to[0] - normal[0], screenSize[1] - pos[1] + this.to[1] - normal[1], 0, this.toColor || this.getColor())
543
599
  ];
544
600
  this.vertexCache.setCache(resBuffer);
545
601
  return resBuffer;
@@ -547,13 +603,11 @@ export class Line2d extends SimulationElement {
547
603
  return this.vertexCache.getCache();
548
604
  }
549
605
  }
550
- export class Cube extends SimulationElement {
606
+ export class Cube extends SimulationElement3d {
551
607
  vertices;
552
- rotation;
553
608
  width;
554
609
  height;
555
610
  depth;
556
- wireframe;
557
611
  wireframeLines;
558
612
  static wireframeOrder = [
559
613
  [0, 1],
@@ -570,12 +624,11 @@ export class Cube extends SimulationElement {
570
624
  [2, 6]
571
625
  ];
572
626
  constructor(pos, width, height, depth, color, rotation) {
573
- super(pos, color);
627
+ super(pos, rotation, color);
574
628
  this.width = width * devicePixelRatio;
575
629
  this.height = height * devicePixelRatio;
576
630
  this.depth = depth * devicePixelRatio;
577
631
  this.rotation = rotation || vector3();
578
- this.wireframe = false;
579
632
  this.wireframeLines = [];
580
633
  const numWireframeLines = 12;
581
634
  const lineThickness = 0.025;
@@ -587,7 +640,6 @@ export class Cube extends SimulationElement {
587
640
  this.shiftWireframeLines();
588
641
  }
589
642
  computeVertices() {
590
- console.log(this.width, this.height);
591
643
  this.vertices = [
592
644
  // front face
593
645
  vector3(-this.width / 2, -this.height / 2, this.depth / 2),
@@ -619,35 +671,6 @@ export class Cube extends SimulationElement {
619
671
  line.setEnd(endPoint);
620
672
  });
621
673
  }
622
- setWireframe(wireframe) {
623
- this.wireframe = wireframe;
624
- }
625
- rotate(amount, t = 0, f) {
626
- const finalRotation = cloneBuf(this.rotation);
627
- vec3.add(finalRotation, amount, finalRotation);
628
- return transitionValues((p) => {
629
- this.rotation[0] += amount[0] * p;
630
- this.rotation[1] += amount[1] * p;
631
- this.rotation[2] += amount[2] * p;
632
- this.vertexCache.updated();
633
- }, () => {
634
- this.rotation = finalRotation;
635
- this.vertexCache.updated();
636
- }, t, f);
637
- }
638
- setRotation(rot, t = 0, f) {
639
- const diff = vector3();
640
- vec3.sub(rot, this.rotation, diff);
641
- return transitionValues((p) => {
642
- this.rotation[0] += diff[0] * p;
643
- this.rotation[1] += diff[1] * p;
644
- this.rotation[2] += diff[2] * p;
645
- this.vertexCache.updated();
646
- }, () => {
647
- this.rotation = rot;
648
- this.vertexCache.updated();
649
- }, t, f);
650
- }
651
674
  setWidth(width, t = 0, f) {
652
675
  width *= devicePixelRatio;
653
676
  const diff = width - this.width;
@@ -700,7 +723,21 @@ export class Cube extends SimulationElement {
700
723
  this.vertexCache.updated();
701
724
  }, t, f);
702
725
  }
703
- getBuffer(camera, force) {
726
+ getWireframe(_, force) {
727
+ if (this.wireframeCache.shouldUpdate() || force) {
728
+ // prettier-ignore
729
+ const lineOrder = [
730
+ 0, 1, 2, 3, 0, 2,
731
+ 6, 5, 1, 6,
732
+ 7, 4, 5, 7,
733
+ 3, 4, 0,
734
+ 5, 6, 3
735
+ ];
736
+ return this.wireframeFromVertexOrder(this.vertices, lineOrder);
737
+ }
738
+ return this.wireframeCache.getCache();
739
+ }
740
+ getTriangles(_, force) {
704
741
  if (this.vertexCache.shouldUpdate() || force) {
705
742
  this.computeVertices();
706
743
  this.shiftWireframeLines();
@@ -721,13 +758,8 @@ export class Cube extends SimulationElement {
721
758
  triangleOrder.forEach((index) => {
722
759
  const vertex = cloneBuf(this.vertices[index]);
723
760
  vec3.transformMat4(vertex, rotMatrix, vertex);
724
- resBuffer = resBuffer.concat(vertexBuffer3d(vertex[0] + pos[0], vertex[1] + pos[1], vertex[2] + pos[2], this.getColor()));
761
+ resBuffer = resBuffer.concat(vertexBuffer(vertex[0] + pos[0], vertex[1] + pos[1], vertex[2] + pos[2], this.getColor()));
725
762
  });
726
- if (this.wireframe) {
727
- this.wireframeLines.forEach((line) => {
728
- resBuffer = resBuffer.concat(line.getBuffer(camera, force));
729
- });
730
- }
731
763
  this.vertexCache.setCache(resBuffer);
732
764
  return resBuffer;
733
765
  }
@@ -838,7 +870,7 @@ export class SplinePoint2d {
838
870
  if (this.end.getColor()) {
839
871
  colors[1] = this.end.getColor();
840
872
  }
841
- if (colors.at(-1) === null) {
873
+ if (colors.length > 2 && colors.at(-1) === null) {
842
874
  colors.pop();
843
875
  }
844
876
  return colors;
@@ -917,7 +949,6 @@ export class Spline2d extends SimulationElement {
917
949
  if (index === this.curves.length)
918
950
  index--;
919
951
  const diff = (t - curveInterval * index) * 2;
920
- console.log(index);
921
952
  return this.curves[index].interpolateSlope(diff);
922
953
  }
923
954
  interpolate(t) {
@@ -962,9 +993,7 @@ export class Spline2d extends SimulationElement {
962
993
  const normal = vector2(-slope[1], slope[0]);
963
994
  vec2.normalize(normal, normal);
964
995
  vec2.scale(normal, this.thickness / 2, normal);
965
- const colorsBefore = this.curves[i].getColors();
966
- console.log(colorsBefore);
967
- const colors = colorsBefore.map((c) => (c ? c : this.getColor()));
996
+ const colors = this.curves[i].getColors().map((c) => (c ? c : this.getColor()));
968
997
  const vertexColor = interpolateColors(colors, currentInterpolation);
969
998
  const vertTop = vertex(point[0] + normal[0], point[1] + normal[1], 0, vertexColor);
970
999
  verticesTop.push(vertTop);
@@ -981,7 +1010,7 @@ export class Spline2d extends SimulationElement {
981
1010
  .flat()
982
1011
  .forEach((vert) => {
983
1012
  const pos = vert.getPos();
984
- resBuffer = resBuffer.concat(vertexBuffer2d(pos[0], pos[1], vert.getColor() || this.getColor()));
1013
+ resBuffer = resBuffer.concat(vertexBuffer(pos[0], pos[1], 0, vert.getColor() || this.getColor()));
985
1014
  });
986
1015
  this.vertexCache.setCache(resBuffer);
987
1016
  return resBuffer;
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
1
  export * from './simulation.js';
2
2
  export * from './graphics.js';
3
3
  export * from './types.js';
4
- export { Vertex, Color, cloneBuf, vector4, vector3, vector2, vector3FromVector2, colorFromVector4, randomInt, randomColor, vertex, color, colorf, transitionValues, lerp, smoothStep, linearStep, splinePoint2d, continuousSplinePoint2d, easeInOutQuad, easeInOutExpo, easeInOutQuart } from './utils.js';
4
+ export { Vertex, Color, cloneBuf, vector4, vector3, vector2, vector3FromVector2, colorFromVector4, randomInt, randomColor, vertex, color, colorf, transitionValues, lerp, smoothStep, linearStep, splinePoint2d, continuousSplinePoint2d, easeInOutQuad, easeInOutExpo, easeInOutQuart, waitFor } from './utils.js';
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
1
  export * from './simulation.js';
2
2
  export * from './graphics.js';
3
3
  export * from './types.js';
4
- export { Vertex, Color, cloneBuf, vector4, vector3, vector2, vector3FromVector2, colorFromVector4, randomInt, randomColor, vertex, color, colorf, transitionValues, lerp, smoothStep, linearStep, splinePoint2d, continuousSplinePoint2d, easeInOutQuad, easeInOutExpo, easeInOutQuart } from './utils.js';
4
+ export { Vertex, Color, cloneBuf, vector4, vector3, vector2, vector3FromVector2, colorFromVector4, randomInt, randomColor, vertex, color, colorf, transitionValues, lerp, smoothStep, linearStep, splinePoint2d, continuousSplinePoint2d, easeInOutQuad, easeInOutExpo, easeInOutQuart, waitFor } from './utils.js';
@@ -1,11 +1,10 @@
1
1
  import { vec3 } from 'wgpu-matrix';
2
- import { SimulationElement } from './graphics.js';
2
+ import { SimulationElement, SimulationElement3d } from './graphics.js';
3
3
  import { BUF_LEN } from './constants.js';
4
4
  import { Color, applyElementToScene, buildDepthTexture, buildMultisampleTexture, buildProjectionMatrix, getOrthoMatrix, getTransformationMatrix, logger, transitionValues, vector2, vector3 } from './utils.js';
5
- const vertexSize = 44; // 4 * 10 + 1
5
+ const vertexSize = 40; // 4 * 10
6
6
  const colorOffset = 16; // 4 * 4
7
7
  const uvOffset = 32; // 4 * 8
8
- const is3dOffset = 40; // 4 * 10
9
8
  const shader = `
10
9
  struct Uniforms {
11
10
  modelViewProjectionMatrix : mat4x4<f32>,
@@ -23,19 +22,29 @@ struct VertexOutput {
23
22
  }
24
23
 
25
24
  @vertex
26
- fn vertex_main(
25
+ fn vertex_main_3d(
27
26
  @location(0) position : vec4<f32>,
28
27
  @location(1) color : vec4<f32>,
29
28
  @location(2) uv : vec2<f32>,
30
- @location(3) is3d : f32
31
29
  ) -> VertexOutput {
32
30
  var output : VertexOutput;
33
31
 
34
- if is3d == 1 {
35
- output.Position = uniforms.modelViewProjectionMatrix * position;
36
- } else {
37
- output.Position = uniforms.orthoProjectionMatrix * position;
38
- }
32
+ output.Position = uniforms.modelViewProjectionMatrix * position;
33
+ output.fragUV = uv;
34
+ output.fragPosition = position;
35
+ output.fragColor = color;
36
+ return output;
37
+ }
38
+
39
+ @vertex
40
+ fn vertex_main_2d(
41
+ @location(0) position : vec4<f32>,
42
+ @location(1) color : vec4<f32>,
43
+ @location(2) uv : vec2<f32>,
44
+ ) -> VertexOutput {
45
+ var output : VertexOutput;
46
+
47
+ output.Position = uniforms.orthoProjectionMatrix * position;
39
48
  output.fragUV = uv;
40
49
  output.fragPosition = position;
41
50
  output.fragColor = color;
@@ -178,11 +187,11 @@ export class Simulation {
178
187
  format: presentationFormat,
179
188
  alphaMode: 'premultiplied'
180
189
  });
181
- const pipeline = device.createRenderPipeline({
190
+ const pipeline2d = device.createRenderPipeline({
182
191
  layout: 'auto',
183
192
  vertex: {
184
193
  module: shaderModule,
185
- entryPoint: 'vertex_main',
194
+ entryPoint: 'vertex_main_2d',
186
195
  buffers: [
187
196
  {
188
197
  arrayStride: vertexSize,
@@ -204,12 +213,58 @@ export class Simulation {
204
213
  shaderLocation: 2,
205
214
  offset: uvOffset,
206
215
  format: 'float32x2'
216
+ }
217
+ ]
218
+ }
219
+ ]
220
+ },
221
+ fragment: {
222
+ module: shaderModule,
223
+ entryPoint: 'fragment_main',
224
+ targets: [
225
+ {
226
+ format: presentationFormat
227
+ }
228
+ ]
229
+ },
230
+ primitive: {
231
+ topology: 'triangle-list'
232
+ },
233
+ multisample: {
234
+ count: 4
235
+ },
236
+ depthStencil: {
237
+ depthWriteEnabled: true,
238
+ depthCompare: 'less',
239
+ format: 'depth24plus'
240
+ }
241
+ });
242
+ const pipeline3d = device.createRenderPipeline({
243
+ layout: 'auto',
244
+ vertex: {
245
+ module: shaderModule,
246
+ entryPoint: 'vertex_main_3d',
247
+ buffers: [
248
+ {
249
+ arrayStride: vertexSize,
250
+ attributes: [
251
+ {
252
+ // position
253
+ shaderLocation: 0,
254
+ offset: 0,
255
+ format: 'float32x4'
207
256
  },
208
257
  {
209
- // is3d
210
- shaderLocation: 3,
211
- offset: is3dOffset,
212
- format: 'float32'
258
+ // color
259
+ shaderLocation: 1,
260
+ offset: colorOffset,
261
+ format: 'float32x4'
262
+ },
263
+ {
264
+ // size
265
+ shaderLocation: 2,
266
+ offset: uvOffset,
267
+ format: 'float32x2'
213
268
  }
214
269
  ]
215
270
  }
@@ -236,13 +291,65 @@ export class Simulation {
236
291
  format: 'depth24plus'
237
292
  }
238
293
  });
294
+ const wireframePipeline = device.createRenderPipeline({
295
+ layout: 'auto',
296
+ vertex: {
297
+ module: shaderModule,
298
+ entryPoint: 'vertex_main_3d',
299
+ buffers: [
300
+ {
301
+ arrayStride: vertexSize,
302
+ attributes: [
303
+ {
304
+ // position
305
+ shaderLocation: 0,
306
+ offset: 0,
307
+ format: 'float32x4'
308
+ },
309
+ {
310
+ // color
311
+ shaderLocation: 1,
312
+ offset: colorOffset,
313
+ format: 'float32x4'
314
+ },
315
+ {
316
+ // size
317
+ shaderLocation: 2,
318
+ offset: uvOffset,
319
+ format: 'float32x2'
320
+ }
321
+ ]
322
+ }
323
+ ]
324
+ },
325
+ fragment: {
326
+ module: shaderModule,
327
+ entryPoint: 'fragment_main',
328
+ targets: [
329
+ {
330
+ format: presentationFormat
331
+ }
332
+ ]
333
+ },
334
+ primitive: {
335
+ topology: 'line-strip'
336
+ },
337
+ multisample: {
338
+ count: 4
339
+ },
340
+ depthStencil: {
341
+ depthWriteEnabled: true,
342
+ depthCompare: 'less',
343
+ format: 'depth24plus'
344
+ }
345
+ });
239
346
  const uniformBufferSize = 4 * 16 + 4 * 16 + 4 * 2 + 8; // 4x4 matrix + 4x4 matrix + vec2<f32> + 8 bc 144 is cool
240
347
  const uniformBuffer = device.createBuffer({
241
348
  size: uniformBufferSize,
242
349
  usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST
243
350
  });
244
351
  const uniformBindGroup = device.createBindGroup({
245
- layout: pipeline.getBindGroupLayout(0),
352
+ layout: pipeline3d.getBindGroupLayout(0),
246
353
  entries: [
247
354
  {
248
355
  binding: 0,
@@ -324,27 +431,35 @@ export class Simulation {
324
431
  orthoMatrix.buffer, orthoMatrix.byteOffset, orthoMatrix.byteLength);
325
432
  device.queue.writeBuffer(uniformBuffer, 4 * 16 + 4 * 16, // 4x4 matrix + 4x4 matrix
326
433
  screenSize.buffer, screenSize.byteOffset, screenSize.byteLength);
327
- let vertexArray = [];
328
- for (let i = 0; i < this.scene.length; i++) {
329
- const buffer = this.scene[i].getBuffer(this.camera, this.camera.hasUpdated());
330
- vertexArray = vertexArray.concat(buffer);
331
- }
332
- this.camera.updateConsumed();
333
- const vertexF32Array = new Float32Array(vertexArray);
334
- const vertexBuffer = device.createBuffer({
335
- size: vertexF32Array.byteLength,
336
- usage: GPUBufferUsage.VERTEX,
337
- mappedAtCreation: true
338
- });
339
- new Float32Array(vertexBuffer.getMappedRange()).set(vertexF32Array);
340
- vertexBuffer.unmap();
341
- const vertexCount = vertexF32Array.length / BUF_LEN;
342
434
  const commandEncoder = device.createCommandEncoder();
343
435
  const passEncoder = commandEncoder.beginRenderPass(renderPassDescriptor);
344
- passEncoder.setPipeline(pipeline);
436
+ passEncoder.setPipeline(pipeline3d);
345
437
  passEncoder.setBindGroup(0, uniformBindGroup);
346
- passEncoder.setVertexBuffer(0, vertexBuffer);
347
- passEncoder.draw(vertexCount);
438
+ for (let i = 0; i < this.scene.length; i++) {
439
+ const buffer = this.scene[i].getBuffer(this.camera, this.camera.hasUpdated());
440
+ const vertexF32Array = new Float32Array(buffer);
441
+ const vertexBuffer = device.createBuffer({
442
+ size: vertexF32Array.byteLength,
443
+ usage: GPUBufferUsage.VERTEX,
444
+ mappedAtCreation: true
445
+ });
446
+ new Float32Array(vertexBuffer.getMappedRange()).set(vertexF32Array);
447
+ vertexBuffer.unmap();
448
+ const vertexCount = vertexF32Array.length / BUF_LEN;
449
+ if (this.scene[i] instanceof SimulationElement3d) {
450
+ if (this.scene[i].isWireframe()) {
451
+ passEncoder.setPipeline(wireframePipeline);
452
+ }
453
+ else {
454
+ passEncoder.setPipeline(pipeline3d);
455
+ }
456
+ }
457
+ else {
458
+ passEncoder.setPipeline(pipeline2d);
459
+ }
460
+ passEncoder.setVertexBuffer(0, vertexBuffer);
461
+ passEncoder.draw(vertexCount);
462
+ }
348
463
  passEncoder.end();
349
464
  device.queue.submit([commandEncoder.finish()]);
350
465
  };
package/dist/utils.d.ts CHANGED
@@ -77,8 +77,7 @@ export declare function linearStep(t: number): number;
77
77
  export declare function easeInOutExpo(t: number): number;
78
78
  export declare function easeInOutQuart(t: number): number;
79
79
  export declare function easeInOutQuad(t: number): number;
80
- export declare function vertexBuffer3d(x: number, y: number, z: number, color: Color, uv?: Vector2): number[];
81
- export declare function vertexBuffer2d(x: number, y: number, color: Color, uv?: Vector2): number[];
80
+ export declare function vertexBuffer(x: number, y: number, z: number, color: Color, uv?: Vector2): number[];
82
81
  export declare function vec3ToPixelRatio(vec: Vector3): void;
83
82
  export declare function cloneBuf<T extends Float32Array>(buf: T): T;
84
83
  export declare function vector4(x?: number, y?: number, z?: number, w?: number): Vector4;
@@ -95,4 +94,8 @@ export declare function colorf(val: number, a?: number): Color;
95
94
  export declare function splinePoint2d(end: Vertex, control1: Vector2, control2: Vector2, detail?: number): SplinePoint2d;
96
95
  export declare function continuousSplinePoint2d(end: Vertex, control: Vector2, detail?: number): SplinePoint2d;
97
96
  export declare function interpolateColors(colors: Color[], t: number): Color;
97
+ /**
98
+ * @param t - seconds
99
+ */
100
+ export declare function waitFor(t: number): Promise<unknown>;
98
101
  export {};
package/dist/utils.js CHANGED
@@ -100,9 +100,9 @@ export class Vertex {
100
100
  }
101
101
  toBuffer(defaultColor) {
102
102
  if (this.is3d)
103
- return vertexBuffer3d(this.pos[0], this.pos[1], this.pos[2], this.color || defaultColor, this.uv);
103
+ return vertexBuffer(this.pos[0], this.pos[1], this.pos[2], this.color || defaultColor, this.uv);
104
104
  else
105
- return vertexBuffer2d(this.pos[0], this.pos[1], this.color || defaultColor, this.uv);
105
+ return vertexBuffer(this.pos[0], this.pos[1], 0, this.color || defaultColor, this.uv);
106
106
  }
107
107
  }
108
108
  export const buildProjectionMatrix = (aspectRatio, zNear = 1, zFar = 500) => {
@@ -263,11 +263,8 @@ export function easeInOutQuart(t) {
263
263
  export function easeInOutQuad(t) {
264
264
  return t < 0.5 ? 2 * t * t : 1 - Math.pow(-2 * t + 2, 2) / 2;
265
265
  }
266
- export function vertexBuffer3d(x, y, z, color, uv = vector2()) {
267
- return [x, y, z, 1, ...color.toBuffer(), ...uv, 1];
268
- }
269
- export function vertexBuffer2d(x, y, color, uv = vector2()) {
270
- return [x, y, 0, 1, ...color.toBuffer(), ...uv, 0];
266
+ export function vertexBuffer(x, y, z, color, uv = vector2()) {
267
+ return [x, y, z, 1, ...color.toBuffer(), ...uv];
271
268
  }
272
269
  export function vec3ToPixelRatio(vec) {
273
270
  vec3.mul(vec, vector3(devicePixelRatio, devicePixelRatio, devicePixelRatio), vec);
@@ -331,8 +328,6 @@ export function interpolateColors(colors, t) {
331
328
  return colors[0];
332
329
  const colorInterval = 1 / colors.length;
333
330
  let index = Math.floor(t / colorInterval);
334
- if (index === -1)
335
- console.log(t);
336
331
  if (index >= colors.length)
337
332
  index = colors.length - 1;
338
333
  const from = index === colors.length - 1 ? colors[index - 1] : colors[index];
@@ -350,3 +345,11 @@ export function interpolateColors(colors, t) {
350
345
  res.a += diff.a;
351
346
  return res;
352
347
  }
348
+ /**
349
+ * @param t - seconds
350
+ */
351
+ export function waitFor(t) {
352
+ return new Promise((resolve) => {
353
+ setTimeout(resolve, t * 1000);
354
+ });
355
+ }
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.2.2",
8
+ "version": "0.2.4",
9
9
  "exports": {
10
10
  ".": {
11
11
  "import": "./dist/index.js",