simulationjsv2 0.1.4 → 0.1.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,5 +1,5 @@
1
1
  import { Camera, Color } from './simulation.js';
2
- import type { Vector2, Vector3, LerpFunc, VertexColorMap } from './types.js';
2
+ import type { Vector2, Vector3, LerpFunc, VertexColorMap, Vector4 } from './types.js';
3
3
  declare class VertexCache {
4
4
  private vertices;
5
5
  private hasUpdated;
@@ -10,14 +10,22 @@ declare class VertexCache {
10
10
  shouldUpdate(): boolean;
11
11
  getVertexCount(): number;
12
12
  }
13
- declare class Vertex {
14
- private readonly pos;
15
- private readonly color;
16
- private readonly is3d;
13
+ export declare class Vertex {
14
+ private pos;
15
+ private color;
16
+ private is3d;
17
17
  private readonly uv;
18
18
  constructor(x?: number, y?: number, z?: number, color?: Color, is3dPoint?: boolean, uv?: Vector2);
19
19
  getPos(): Vector3;
20
20
  getColor(): Color | null;
21
+ getUv(): Vector2;
22
+ setColor(color: Color): void;
23
+ setPos(pos: Vector3): void;
24
+ setX(x: number): void;
25
+ setY(y: number): void;
26
+ setZ(z: number): void;
27
+ setIs3d(is3d: boolean): void;
28
+ clone(): Vertex;
21
29
  toBuffer(defaultColor: Color): number[];
22
30
  }
23
31
  export declare abstract class SimulationElement {
@@ -38,7 +46,7 @@ export declare abstract class SimulationElement {
38
46
  export declare class Plane extends SimulationElement {
39
47
  private points;
40
48
  private rotation;
41
- constructor(pos: Vector3, points: Vertex[], rotation?: Vector3, color?: Color);
49
+ constructor(pos: Vector3, points: Vertex[], color?: Color, rotation?: Vector3);
42
50
  setPoints(newPoints: Vertex[]): void;
43
51
  rotate(amount: Vector3, t?: number, f?: LerpFunc): Promise<void>;
44
52
  rotateTo(angle: Vector3, t?: number, f?: LerpFunc): Promise<void>;
@@ -72,20 +80,22 @@ export declare class Circle extends SimulationElement {
72
80
  getBuffer(camera: Camera, force: boolean): number[];
73
81
  }
74
82
  export declare class Polygon extends SimulationElement {
75
- private points;
83
+ private vertices;
76
84
  private rotation;
77
- constructor(pos: Vector3, points: Vector2[], color?: Color);
85
+ constructor(pos: Vector3, vertices: Vertex[], color?: Color);
78
86
  rotate(amount: number, t?: number, f?: LerpFunc): Promise<void>;
79
87
  rotateTo(num: number, t?: number, f?: LerpFunc): Promise<void>;
80
- setPoints(newPoints: Vector3[], t?: number, f?: LerpFunc): Promise<void>;
81
- getBuffer(): never[];
88
+ setPoints(newVertices: Vertex[], t?: number, f?: LerpFunc): Promise<void>;
89
+ getBuffer(camera: Camera, force: boolean): number[];
82
90
  }
91
+ export declare function vector4(x?: number, y?: number, z?: number, w?: number): Vector4;
83
92
  export declare function vector3(x?: number, y?: number, z?: number): Vector3;
84
93
  export declare function vector2(x?: number, y?: number): Vector2;
85
94
  export declare function vec3fromVec2(vec: Vector2): Vector3;
95
+ export declare function colorFromVec4(vec: Vector4): Color;
86
96
  export declare function randomInt(range: number, min?: number): number;
87
97
  export declare function randomColor(a?: number): Color;
88
- export declare function vertex(x?: number, y?: number, z?: number, color?: Color): Vertex;
98
+ export declare function vertex(x?: number, y?: number, z?: number, color?: Color, is3dPoint?: boolean, uv?: Vector2): Vertex;
89
99
  export declare function color(r?: number, g?: number, b?: number, a?: number): Color;
90
100
  export declare function colorf(val: number, a?: number): Color;
91
101
  export {};
package/dist/graphics.js CHANGED
@@ -1,4 +1,4 @@
1
- import { vec3, quat, mat4, vec2 } from 'wgpu-matrix';
1
+ import { vec3, quat, mat4, vec2, vec4 } from 'wgpu-matrix';
2
2
  import { Color, transitionValues } from './simulation.js';
3
3
  import { BUF_LEN } from './constants.js';
4
4
  class VertexCache {
@@ -22,7 +22,7 @@ class VertexCache {
22
22
  return this.vertices.length / BUF_LEN;
23
23
  }
24
24
  }
25
- class Vertex {
25
+ export class Vertex {
26
26
  pos;
27
27
  color;
28
28
  is3d;
@@ -39,11 +39,35 @@ class Vertex {
39
39
  getColor() {
40
40
  return this.color;
41
41
  }
42
+ getUv() {
43
+ return this.uv;
44
+ }
45
+ setColor(color) {
46
+ this.color = color;
47
+ }
48
+ setPos(pos) {
49
+ this.pos = pos;
50
+ }
51
+ setX(x) {
52
+ this.pos[0] = x;
53
+ }
54
+ setY(y) {
55
+ this.pos[1] = y;
56
+ }
57
+ setZ(z) {
58
+ this.pos[2] = z;
59
+ }
60
+ setIs3d(is3d) {
61
+ this.is3d = is3d;
62
+ }
63
+ clone() {
64
+ return new Vertex(this.pos[0], this.pos[1], this.pos[2], this.color?.clone(), this.is3d, cloneBuf(this.uv));
65
+ }
42
66
  toBuffer(defaultColor) {
43
67
  if (this.is3d)
44
- return vertexBuffer3d(this.pos, this.color || defaultColor, this.uv);
68
+ return vertexBuffer3d(this.pos[0], this.pos[1], this.pos[2], this.color || defaultColor, this.uv);
45
69
  else
46
- return vertexBuffer2d(this.pos, this.color || defaultColor, this.uv);
70
+ return vertexBuffer2d(this.pos[0], this.pos[1], this.color || defaultColor, this.uv);
47
71
  }
48
72
  }
49
73
  export class SimulationElement {
@@ -119,7 +143,7 @@ export class SimulationElement {
119
143
  export class Plane extends SimulationElement {
120
144
  points;
121
145
  rotation;
122
- constructor(pos, points, rotation = vector3(), color) {
146
+ constructor(pos, points, color, rotation = vector3()) {
123
147
  super(pos, color);
124
148
  this.points = points;
125
149
  this.rotation = rotation;
@@ -155,8 +179,8 @@ export class Plane extends SimulationElement {
155
179
  }
156
180
  getBuffer(_, force) {
157
181
  if (this.vertexCache.shouldUpdate() || force) {
158
- const resBuffer = [];
159
- const triangles = generateTriangles(this.points).flat();
182
+ let resBuffer = [];
183
+ const triangles = lossyTriangulate(this.points).flat();
160
184
  triangles.forEach((verticy) => {
161
185
  const rot = quat.create();
162
186
  quat.fromEuler(...this.rotation, 'xyz', rot);
@@ -167,7 +191,7 @@ export class Plane extends SimulationElement {
167
191
  vec3.add(out, this.getPos(), out);
168
192
  let vertexColor = verticy.getColor();
169
193
  vertexColor = vertexColor ? vertexColor : this.getColor();
170
- resBuffer.push(...vertexBuffer3d(out, vertexColor));
194
+ resBuffer = resBuffer.concat(vertexBuffer3d(out[0], out[1], out[2], vertexColor));
171
195
  });
172
196
  this.vertexCache.setCache(resBuffer);
173
197
  return resBuffer;
@@ -277,25 +301,25 @@ export class Square extends SimulationElement {
277
301
  }, t, f);
278
302
  }
279
303
  getBuffer(camera, force) {
280
- const resBuffer = [];
281
- const vertexOrder = [0, 1, 2, 0, 2, 3];
282
304
  if (this.vertexCache.shouldUpdate() || force) {
305
+ let resBuffer = [];
306
+ const vertexOrder = [0, 1, 2, 0, 2, 3];
283
307
  const rotationMat = mat4.identity();
284
308
  mat4.rotateZ(rotationMat, this.rotation, rotationMat);
285
309
  const points = this.points.map((vec) => {
286
- vec2.transformMat4(vec, rotationMat, vec);
287
310
  const pos = vector2();
288
- vec2.clone(this.getPos(), pos);
311
+ vec2.add(vec, pos, pos);
312
+ vec2.transformMat4(vec, rotationMat, pos);
313
+ vec2.add(vec, this.getPos(), pos);
289
314
  pos[1] = camera.getScreenSize()[1] - pos[1];
290
315
  pos[0] += this.width / 2;
291
316
  pos[1] -= this.height / 2;
292
- vec2.add(vec, pos, vec);
293
- return vec;
317
+ return pos;
294
318
  });
295
319
  vertexOrder.forEach((vertex) => {
296
320
  let vertexColor = this.vertexColors[vertex];
297
321
  vertexColor = vertexColor ? vertexColor : this.getColor();
298
- resBuffer.push(...vertexBuffer2d(vec3fromVec2(points[vertex]), vertexColor));
322
+ resBuffer = resBuffer.concat(vertexBuffer2d(points[vertex][0], points[vertex][1], vertexColor));
299
323
  });
300
324
  this.vertexCache.setCache(resBuffer);
301
325
  return resBuffer;
@@ -346,7 +370,7 @@ export class Circle extends SimulationElement {
346
370
  const screenSize = camera.getScreenSize();
347
371
  points.push(new Vertex(vec[0], screenSize[1] - vec[1], vec[2], this.getColor(), false));
348
372
  }
349
- const vertices = generateTriangles(points).reduce((acc, curr) => {
373
+ const vertices = lossyTriangulate(points).reduce((acc, curr) => {
350
374
  curr.forEach((vertex) => acc.push(...vertex.toBuffer(this.getColor())));
351
375
  return acc;
352
376
  }, []);
@@ -357,15 +381,15 @@ export class Circle extends SimulationElement {
357
381
  }
358
382
  }
359
383
  export class Polygon extends SimulationElement {
360
- points;
384
+ vertices;
361
385
  rotation = 0;
362
- /*
363
- * points adjusted for device pixel ratio
364
- */
365
- constructor(pos, points, color) {
386
+ constructor(pos, vertices, color) {
366
387
  super(pos, color);
367
- this.points = points.map((point) => {
368
- return new Vertex(point[0], point[1], 0, this.getColor(), false);
388
+ this.vertices = vertices.map((vertex) => {
389
+ const newVertex = vertex.clone();
390
+ newVertex.setZ(0);
391
+ newVertex.setIs3d(false);
392
+ return vertex;
369
393
  });
370
394
  }
371
395
  rotate(amount, t = 0, f) {
@@ -386,66 +410,96 @@ export class Polygon extends SimulationElement {
386
410
  this.rotation = num;
387
411
  }, t, f);
388
412
  }
389
- setPoints(newPoints, t = 0, f) {
390
- const points = newPoints.map((point) => {
391
- const vec = vector3(...point);
392
- return vec;
413
+ setPoints(newVertices, t = 0, f) {
414
+ const vertices = newVertices.map((vert) => {
415
+ const newVertex = vert.clone();
416
+ newVertex.setZ(0);
417
+ newVertex.setIs3d(false);
418
+ return newVertex;
393
419
  });
394
- const lastPoint = this.points.length > 0 ? this.points[this.points.length - 1] : vec3.create();
395
- if (points.length > this.points.length) {
396
- while (points.length > this.points.length) {
397
- this.points.push(new Vertex(lastPoint[0], lastPoint[1], 0, this.getColor(), false));
420
+ const lastVert = this.vertices.length > 0 ? this.vertices[this.vertices.length - 1] : vertex(0, 0, 0, color(), false);
421
+ if (vertices.length > this.vertices.length) {
422
+ while (vertices.length > this.vertices.length) {
423
+ const lastPos = lastVert.getPos();
424
+ this.vertices.push(new Vertex(lastPos[0], lastPos[1], 0, lastVert.getColor() || this.getColor(), false));
398
425
  }
399
426
  }
400
- const initial = this.points.map((p) => vector3(...p.getPos()));
401
- const changes = [
402
- ...points.map((p, i) => {
403
- const vec = vec3.create();
404
- vec3.sub(vec, p, this.points[i]);
405
- return vec;
427
+ const initialPositions = this.vertices.map((p) => cloneBuf(p.getPos()));
428
+ const posChanges = [
429
+ ...vertices.map((vert, i) => {
430
+ const vec = vector3();
431
+ vec3.sub(vert.getPos(), this.vertices[i].getPos(), vec);
432
+ return cloneBuf(vec);
406
433
  }),
407
- ...this.points.slice(points.length, this.points.length).map((point) => {
408
- const vec = vector3(...points[points.length - 1]) || vec3.create();
409
- vec3.sub(vec, vec, point);
410
- return vec;
411
- })
434
+ ...(this.vertices.length > vertices.length
435
+ ? this.vertices.slice(vertices.length, this.vertices.length).map((vert) => {
436
+ const vec = cloneBuf(vertices[vertices.length - 1].getPos());
437
+ vec3.sub(vec, vert.getPos(), vec);
438
+ return vec;
439
+ })
440
+ : [])
441
+ ];
442
+ const initialColors = this.vertices.map((vert) => (vert.getColor() || this.getColor()).toVec4());
443
+ const colorChanges = [
444
+ ...vertices.map((vert, i) => {
445
+ const diff = (vert.getColor() || this.getColor()).diff(this.vertices[i].getColor() || this.getColor());
446
+ return diff.toVec4();
447
+ }),
448
+ ...(this.vertices.length > vertices.length
449
+ ? this.vertices.slice(vertices.length, this.vertices.length).map((vert) => {
450
+ const toColor = vertices[vertices.length - 1].getColor();
451
+ return (toColor || this.getColor()).diff(vert.getColor() || this.getColor()).toVec4();
452
+ })
453
+ : [])
412
454
  ];
413
455
  return transitionValues((p) => {
414
- this.points = this.points.map((point, i) => {
415
- const change = vector3(...changes[i]);
416
- vec3.scale(change, change, p);
417
- vec3.add(point, point, change);
418
- return point;
456
+ this.vertices.forEach((vert, i) => {
457
+ const posChange = cloneBuf(posChanges[i]);
458
+ const colorChange = cloneBuf(colorChanges[i]);
459
+ vec3.scale(posChange, p, posChange);
460
+ vec3.add(vert.getPos(), posChange, posChange);
461
+ vec4.scale(colorChange, p, colorChange);
462
+ vec4.add((vert.getColor() || this.getColor()).toVec4(), colorChange, colorChange);
463
+ vert.setPos(posChange);
464
+ vert.setColor(colorFromVec4(colorChange));
419
465
  });
420
466
  this.vertexCache.updated();
421
467
  }, () => {
422
- this.points = initial.map((p, i) => {
423
- const vec = vec3.create();
424
- vec3.add(vec, p, changes[i]);
425
- return vec;
468
+ this.vertices.forEach((vert, i) => {
469
+ const initPos = initialPositions[i];
470
+ const initColor = initialColors[i];
471
+ vec3.add(initPos, posChanges[i], initPos);
472
+ vec4.add(initColor, colorChanges[i], initColor);
473
+ vert.setPos(initPos);
474
+ vert.setColor(colorFromVec4(initColor));
426
475
  });
427
- this.points.splice(points.length, this.points.length);
476
+ this.vertices.splice(vertices.length, this.vertices.length);
428
477
  this.vertexCache.updated();
429
478
  }, t, f);
430
479
  }
431
- getBuffer() {
432
- // let triangles: Triangles = [];
433
- // if (this.triangleCache.shouldUpdate()) {
434
- // let newPoints: vec3[] = this.points.map((vec) => {
435
- // const newPoint = vec3.create();
436
- // vec3.add(newPoint, vec, this.getPos());
437
- // return newPoint;
438
- // });
439
- // triangles = generateTriangles(newPoints);
440
- // this.triangleCache.setCache(triangles);
441
- // } else {
442
- // triangles = this.triangleCache.getCache();
443
- // }
444
- // return trianglesAndColorToBuffer(triangles, this.getColor());
445
- return [];
480
+ getBuffer(camera, force) {
481
+ if (this.vertexCache.shouldUpdate() || force) {
482
+ let resBuffer = [];
483
+ const rotationMat = mat4.identity();
484
+ mat4.rotateZ(rotationMat, this.rotation, rotationMat);
485
+ lossyTriangulate(this.vertices)
486
+ .flat()
487
+ .forEach((vert) => {
488
+ const pos = vector3();
489
+ vec3.add(vert.getPos(), pos, pos);
490
+ vec3.transformMat4(pos, rotationMat, pos);
491
+ vec3.add(this.getPos(), pos, pos);
492
+ pos[1] = camera.getScreenSize()[1] - pos[1];
493
+ resBuffer = resBuffer.concat(vertexBuffer2d(pos[0], pos[1], vert.getColor() || this.getColor()));
494
+ });
495
+ this.vertexCache.setCache(resBuffer);
496
+ return resBuffer;
497
+ }
498
+ return this.vertexCache.getCache();
446
499
  }
447
500
  }
448
- function generateTriangles(vertices) {
501
+ // optomized for speed, depending on orientation of vertices as input, shape may not be preserved
502
+ function lossyTriangulate(vertices) {
449
503
  const res = [];
450
504
  let facingRight = true;
451
505
  let rightOffset = 0;
@@ -473,11 +527,20 @@ function generateTriangles(vertices) {
473
527
  }
474
528
  return res;
475
529
  }
476
- function vertexBuffer3d(point, color, uv = vector2()) {
477
- return [...point, 1, ...color.toBuffer(), ...uv, 1];
530
+ function vertexBuffer3d(x, y, z, color, uv = vector2()) {
531
+ return [x, y, z, 1, ...color.toBuffer(), ...uv, 1];
478
532
  }
479
- function vertexBuffer2d(point, color, uv = vector2()) {
480
- return [...point, 1, ...color.toBuffer(), ...uv, 0];
533
+ function vertexBuffer2d(x, y, color, uv = vector2()) {
534
+ return [x, y, 0, 1, ...color.toBuffer(), ...uv, 0];
535
+ }
536
+ function vec3ToPixelRatio(vec) {
537
+ vec3.mul(vec, vector3(devicePixelRatio, devicePixelRatio, devicePixelRatio), vec);
538
+ }
539
+ function cloneBuf(buf) {
540
+ return new Float32Array(buf);
541
+ }
542
+ export function vector4(x = 0, y = 0, z = 0, w = 0) {
543
+ return vec4.fromValues(x, y, z, w);
481
544
  }
482
545
  export function vector3(x = 0, y = 0, z = 0) {
483
546
  return vec3.fromValues(x, y, z);
@@ -485,20 +548,20 @@ export function vector3(x = 0, y = 0, z = 0) {
485
548
  export function vector2(x = 0, y = 0) {
486
549
  return vec2.fromValues(x, y, 0);
487
550
  }
488
- function vec3ToPixelRatio(vec) {
489
- vec3.mul(vec, vector3(devicePixelRatio, devicePixelRatio, devicePixelRatio), vec);
490
- }
491
551
  export function vec3fromVec2(vec) {
492
552
  return vector3(vec[0], vec[1]);
493
553
  }
554
+ export function colorFromVec4(vec) {
555
+ return new Color(vec[0], vec[1], vec[2], vec[3]);
556
+ }
494
557
  export function randomInt(range, min = 0) {
495
558
  return Math.floor(Math.random() * (range - min)) + min;
496
559
  }
497
560
  export function randomColor(a = 1) {
498
561
  return new Color(randomInt(255), randomInt(255), randomInt(255), a);
499
562
  }
500
- export function vertex(x, y, z, color) {
501
- return new Vertex(x, y, z, color);
563
+ export function vertex(x, y, z, color, is3dPoint, uv) {
564
+ return new Vertex(x, y, z, color, is3dPoint, uv);
502
565
  }
503
566
  export function color(r, g, b, a) {
504
567
  return new Color(r, g, b, a);
@@ -55,12 +55,14 @@ export declare class Color {
55
55
  constructor(r?: number, g?: number, b?: number, a?: number);
56
56
  clone(): Color;
57
57
  toBuffer(): readonly [number, number, number, number];
58
+ toVec4(): import("./types.js").Vector4;
58
59
  toObject(): {
59
60
  r: number;
60
61
  g: number;
61
62
  b: number;
62
63
  a: number;
63
64
  };
65
+ diff(color: Color): Color;
64
66
  }
65
67
  /**
66
68
  * @param callback1 - called every frame until the animation is finished
@@ -1,5 +1,5 @@
1
1
  import { vec3 } from 'wgpu-matrix';
2
- import { SimulationElement, vector2, vector3 } from './graphics.js';
2
+ import { SimulationElement, vector2, vector3, vector4 } from './graphics.js';
3
3
  import { BUF_LEN } from './constants.js';
4
4
  import { applyElementToScene, buildDepthTexture, buildProjectionMatrix, getOrthoMatrix, getTransformationMatrix, logger } from './utils.js';
5
5
  const vertexSize = 44; // 4 * 10 + 1
@@ -486,6 +486,9 @@ export class Color {
486
486
  toBuffer() {
487
487
  return [this.r / 255, this.g / 255, this.b / 255, this.a];
488
488
  }
489
+ toVec4() {
490
+ return vector4(this.r, this.g, this.b, this.a);
491
+ }
489
492
  toObject() {
490
493
  return {
491
494
  r: this.r / 255,
@@ -494,6 +497,9 @@ export class Color {
494
497
  a: this.a
495
498
  };
496
499
  }
500
+ diff(color) {
501
+ return new Color(this.r - color.r, this.g - color.g, this.b - color.b, this.a - color.a);
502
+ }
497
503
  }
498
504
  /**
499
505
  * @param callback1 - called every frame until the animation is finished
package/dist/types.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import { Color } from './simulation.js';
2
+ export type Vector4 = Float32Array & [number, number, number, number];
2
3
  export type Vector3 = Float32Array & [number, number, number];
3
4
  export type Vector2 = Float32Array & [number, number];
4
5
  export type LerpFunc = (n: number) => number;
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.1.4",
8
+ "version": "0.1.5",
9
9
  "exports": {
10
10
  ".": {
11
11
  "import": "./dist/index.js",