simulationjsv2 0.1.9 → 0.2.0

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,19 +1,19 @@
1
1
  import { Camera } from './simulation.js';
2
2
  import type { Vector2, Vector3, LerpFunc, VertexColorMap } from './types.js';
3
3
  import { Vertex, VertexCache, Color } from './utils.js';
4
- export declare abstract class SimulationElement {
4
+ export declare abstract class SimulationElement<T extends Vector2 | Vector3 = Vector3> {
5
5
  private pos;
6
6
  private color;
7
7
  camera: Camera | null;
8
8
  vertexCache: VertexCache;
9
- constructor(pos: Vector3, color?: Color);
10
- setPos(pos: Vector3): void;
11
- getPos(): Vector3;
9
+ constructor(pos: T, color?: Color);
10
+ setPos(pos: T): void;
11
+ getPos(): T;
12
12
  setCamera(camera: Camera): void;
13
13
  fill(newColor: Color, t?: number, f?: LerpFunc): Promise<void>;
14
14
  getColor(): Color;
15
- move(amount: Vector3, t?: number, f?: LerpFunc): Promise<void>;
16
- moveTo(pos: Vector3, t?: number, f?: LerpFunc): Promise<void>;
15
+ move(amount: T, t?: number, f?: LerpFunc): Promise<void>;
16
+ moveTo(pos: T, t?: number, f?: LerpFunc): Promise<void>;
17
17
  abstract getBuffer(camera: Camera, force: boolean): number[];
18
18
  }
19
19
  export declare class Plane extends SimulationElement {
@@ -25,7 +25,7 @@ export declare class Plane extends SimulationElement {
25
25
  rotateTo(angle: Vector3, t?: number, f?: LerpFunc): Promise<void>;
26
26
  getBuffer(_: Camera, force: boolean): number[];
27
27
  }
28
- export declare class Square extends SimulationElement {
28
+ export declare class Square extends SimulationElement<Vector2> {
29
29
  private width;
30
30
  private height;
31
31
  private rotation;
@@ -44,7 +44,7 @@ export declare class Square extends SimulationElement {
44
44
  setRotation(newRotation: number, t?: number, f?: LerpFunc): Promise<void>;
45
45
  getBuffer(camera: Camera, force: boolean): number[];
46
46
  }
47
- export declare class Circle extends SimulationElement {
47
+ export declare class Circle extends SimulationElement<Vector2> {
48
48
  private radius;
49
49
  private detail;
50
50
  constructor(pos: Vector2, radius: number, color?: Color, detail?: number);
@@ -52,16 +52,56 @@ export declare class Circle extends SimulationElement {
52
52
  scale(amount: number, t?: number, f?: LerpFunc): Promise<void>;
53
53
  getBuffer(camera: Camera, force: boolean): number[];
54
54
  }
55
- export declare class Polygon extends SimulationElement {
55
+ export declare class Polygon extends SimulationElement<Vector2> {
56
56
  private vertices;
57
57
  private rotation;
58
- constructor(pos: Vector3, vertices: Vertex[], color?: Color);
58
+ constructor(pos: Vector2, vertices: Vertex[], color?: Color);
59
59
  rotate(amount: number, t?: number, f?: LerpFunc): Promise<void>;
60
60
  rotateTo(num: number, t?: number, f?: LerpFunc): Promise<void>;
61
61
  getVertices(): Vertex[];
62
62
  setVertices(newVertices: Vertex[], t?: number, f?: LerpFunc): Promise<void>;
63
63
  getBuffer(camera: Camera, force: boolean): number[];
64
64
  }
65
+ export declare class Line3d extends SimulationElement {
66
+ private to;
67
+ private toColor;
68
+ private thickness;
69
+ constructor(pos: Vertex, to: Vertex, thickness: number);
70
+ setStart(pos: Vector3, t?: number, f?: LerpFunc): Promise<void>;
71
+ setEnd(pos: Vector3, t?: number, f?: LerpFunc): Promise<void>;
72
+ getBuffer(_: Camera, force: boolean): number[];
73
+ }
74
+ export declare class Line2d extends SimulationElement {
75
+ private to;
76
+ private toColor;
77
+ private thickness;
78
+ constructor(from: Vertex, to: Vertex, thickness?: number);
79
+ setEndColor(newColor: Color, t?: number, f?: LerpFunc): Promise<void>;
80
+ setStart(pos: Vector2, t?: number, f?: LerpFunc): Promise<void>;
81
+ setEnd(pos: Vector2, t?: number, f?: LerpFunc): Promise<void>;
82
+ getBuffer(camera: Camera, force: boolean): number[];
83
+ }
84
+ export declare class Cube extends SimulationElement {
85
+ private vertices;
86
+ private rotation;
87
+ private width;
88
+ private height;
89
+ private depth;
90
+ private wireframe;
91
+ private wireframeLines;
92
+ private static readonly wireframeOrder;
93
+ constructor(pos: Vector3, width: number, height: number, depth: number, color?: Color, rotation?: Vector3);
94
+ private computeVertices;
95
+ 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
+ setWidth(width: number, t?: number, f?: LerpFunc): Promise<void>;
100
+ setHeight(height: number, t?: number, f?: LerpFunc): Promise<void>;
101
+ setDepth(depth: number, t?: number, f?: LerpFunc): Promise<void>;
102
+ scale(amount: number, t?: number, f?: LerpFunc): Promise<void>;
103
+ getBuffer(camera: Camera, force: boolean): number[];
104
+ }
65
105
  export declare class BezierCurve2d {
66
106
  private points;
67
107
  constructor(points: Vector2[]);
@@ -73,9 +113,9 @@ export declare class BezierCurve2d {
73
113
  export declare class CubicBezierCurve2d extends BezierCurve2d {
74
114
  private detail;
75
115
  private colors;
76
- constructor(points: [Vector2, Vector2, Vector2, Vector2], detail?: number, colors?: Color[]);
116
+ constructor(points: [Vector2, Vector2, Vector2, Vector2], detail?: number, colors?: (Color | null)[]);
77
117
  getDetail(): number | undefined;
78
- getColors(): Color[];
118
+ getColors(): (Color | null)[];
79
119
  }
80
120
  export declare class SplinePoint2d {
81
121
  private start;
@@ -90,16 +130,16 @@ export declare class SplinePoint2d {
90
130
  getControls(): readonly [Vector2 | null, Vector2];
91
131
  getRawControls(): [Vector2, Vector2];
92
132
  getDetail(): number | undefined;
93
- getColors(prevColor?: Color): Color[];
133
+ getColors(prevColor?: Color | null): (Color | null)[];
94
134
  getVectorArray(prevEnd: Vector2 | null, prevControl: Vector2 | null): readonly [Vector2, Vector2, Vector2, Vector2];
95
135
  }
96
136
  export declare class Spline2d extends SimulationElement {
97
137
  private curves;
98
- private width;
138
+ private thickness;
99
139
  private detail;
100
140
  private interpolateLimit;
101
141
  private distance;
102
- constructor(pos: Vertex, points: SplinePoint2d[], width?: number, detail?: number);
142
+ constructor(pos: Vertex, points: SplinePoint2d[], thickness?: number, detail?: number);
103
143
  setInterpolateLimit(limit: number, t?: number, f?: LerpFunc): Promise<void>;
104
144
  getBuffer(camera: Camera, force: boolean): number[];
105
145
  }
package/dist/graphics.js CHANGED
@@ -7,7 +7,7 @@ export class SimulationElement {
7
7
  vertexCache;
8
8
  constructor(pos, color = new Color()) {
9
9
  this.pos = pos;
10
- vec3ToPixelRatio(this.pos);
10
+ vec3ToPixelRatio(vector3(...this.pos));
11
11
  this.color = color;
12
12
  this.vertexCache = new VertexCache();
13
13
  this.camera = null;
@@ -22,16 +22,13 @@ export class SimulationElement {
22
22
  this.camera = camera;
23
23
  }
24
24
  fill(newColor, t = 0, f) {
25
- const diffR = newColor.r - this.color.r;
26
- const diffG = newColor.g - this.color.g;
27
- const diffB = newColor.b - this.color.b;
28
- const diffA = newColor.a - this.color.a;
25
+ const diff = newColor.diff(this.color);
29
26
  const finalColor = newColor.clone();
30
27
  return transitionValues((p) => {
31
- this.color.r += diffR * p;
32
- this.color.g += diffG * p;
33
- this.color.b += diffB * p;
34
- this.color.a += diffA * p;
28
+ this.color.r += diff.r * p;
29
+ this.color.g += diff.g * p;
30
+ this.color.b += diff.b * p;
31
+ this.color.a += diff.a * p;
35
32
  this.vertexCache.updated();
36
33
  }, () => {
37
34
  this.color = finalColor;
@@ -42,13 +39,12 @@ export class SimulationElement {
42
39
  return this.color;
43
40
  }
44
41
  move(amount, t = 0, f) {
45
- const finalPos = vec3.create();
42
+ const finalPos = amount.length === 3 ? vector3() : vector2();
46
43
  vec3.add(finalPos, this.pos, amount);
47
44
  return transitionValues((p) => {
48
- const x = amount[0] * p;
49
- const y = amount[1] * p;
50
- const z = amount[2] * p;
51
- vec3.add(this.pos, this.pos, vector3(x, y, z));
45
+ for (let i = 0; i < this.pos.length; i++) {
46
+ this.pos[i] += amount[i] * p;
47
+ }
52
48
  this.vertexCache.updated();
53
49
  }, () => {
54
50
  this.pos = finalPos;
@@ -56,16 +52,17 @@ export class SimulationElement {
56
52
  }, t, f);
57
53
  }
58
54
  moveTo(pos, t = 0, f) {
59
- const diff = vec3.create();
55
+ const diff = pos.length === 3 ? vector3() : vector2();
60
56
  vec3.sub(diff, pos, this.pos);
61
57
  return transitionValues((p) => {
62
- const x = diff[0] * p;
63
- const y = diff[1] * p;
64
- const z = diff[2] * p;
65
- vec3.add(this.pos, this.pos, vector3(x, y, z));
58
+ for (let i = 0; i < this.pos.length; i++) {
59
+ this.pos[i] += diff[i] * p;
60
+ }
66
61
  this.vertexCache.updated();
67
62
  }, () => {
68
- this.pos = pos;
63
+ for (let i = 0; i < this.pos.length; i++) {
64
+ this.pos[i] = pos[i];
65
+ }
69
66
  this.vertexCache.updated();
70
67
  }, t, f);
71
68
  }
@@ -139,7 +136,7 @@ export class Square extends SimulationElement {
139
136
  * @param vertexColors{Record<number, Color>} - 0 is top left vertex, numbers increase clockwise
140
137
  */
141
138
  constructor(pos, width, height, color, rotation, vertexColors) {
142
- super(vector3FromVector2(pos), color);
139
+ super(pos, color);
143
140
  this.width = width * devicePixelRatio;
144
141
  this.height = height * devicePixelRatio;
145
142
  this.rotation = rotation || 0;
@@ -261,7 +258,7 @@ export class Circle extends SimulationElement {
261
258
  radius;
262
259
  detail = 100;
263
260
  constructor(pos, radius, color, detail = 50) {
264
- super(vector3FromVector2(pos), color);
261
+ super(pos, color);
265
262
  this.radius = radius * devicePixelRatio;
266
263
  this.detail = detail;
267
264
  }
@@ -431,6 +428,308 @@ export class Polygon extends SimulationElement {
431
428
  return this.vertexCache.getCache();
432
429
  }
433
430
  }
431
+ export class Line3d extends SimulationElement {
432
+ to;
433
+ toColor;
434
+ thickness;
435
+ constructor(pos, to, thickness) {
436
+ super(pos.getPos(), to.getColor() || undefined);
437
+ this.thickness = thickness;
438
+ this.toColor = to.getColor() || this.getColor();
439
+ this.to = to.getPos();
440
+ vec3.scale(this.to, devicePixelRatio, this.to);
441
+ vec3.sub(this.to, this.getPos(), this.to);
442
+ }
443
+ setStart(pos, t = 0, f) {
444
+ return this.moveTo(pos, t, f);
445
+ }
446
+ setEnd(pos, t = 0, f) {
447
+ const diff = vector3();
448
+ vec3.sub(pos, this.to, diff);
449
+ return transitionValues((p) => {
450
+ this.to[0] += diff[0] * p;
451
+ this.to[1] += diff[1] * p;
452
+ this.to[2] += diff[2] * p;
453
+ this.vertexCache.updated();
454
+ }, () => {
455
+ this.to[0] = pos[0];
456
+ this.to[1] = pos[1];
457
+ this.to[2] = pos[2];
458
+ this.vertexCache.updated();
459
+ }, t, f);
460
+ }
461
+ getBuffer(_, force) {
462
+ if (this.vertexCache.shouldUpdate() || force) {
463
+ const normal = vector2(-this.to[1], this.to[0]);
464
+ vec2.normalize(normal, normal);
465
+ vec2.scale(normal, this.thickness / 2, normal);
466
+ const pos = this.getPos();
467
+ const resBuffer = [
468
+ ...vertexBuffer3d(pos[0] + normal[0], pos[1] + normal[1], pos[2], this.getColor()),
469
+ ...vertexBuffer3d(pos[0] - normal[0], pos[1] - normal[1], pos[2], this.getColor()),
470
+ ...vertexBuffer3d(pos[0] + this.to[0] + normal[0], pos[1] + this.to[1] + normal[1], pos[2] + this.to[2], this.toColor || this.getColor()),
471
+ ...vertexBuffer3d(pos[0] - normal[0], pos[1] - normal[1], pos[2], this.getColor()),
472
+ ...vertexBuffer3d(pos[0] + this.to[0] + normal[0], pos[1] + this.to[1] + normal[1], pos[2] + this.to[2], this.toColor || this.getColor()),
473
+ ...vertexBuffer3d(pos[0] + this.to[0] - normal[0], pos[1] + this.to[1] - normal[1], pos[2] + this.to[2], this.toColor || this.getColor())
474
+ ];
475
+ this.vertexCache.setCache(resBuffer);
476
+ return resBuffer;
477
+ }
478
+ return this.vertexCache.getCache();
479
+ }
480
+ }
481
+ export class Line2d extends SimulationElement {
482
+ to;
483
+ toColor;
484
+ thickness;
485
+ constructor(from, to, thickness = 1) {
486
+ super(from.getPos(), from.getColor() || undefined);
487
+ this.thickness = thickness * devicePixelRatio;
488
+ this.toColor = to.getColor();
489
+ this.to = vector2FromVector3(to.getPos());
490
+ vec2.scale(this.to, devicePixelRatio, this.to);
491
+ vec2.sub(this.to, this.getPos(), this.to);
492
+ }
493
+ setEndColor(newColor, t = 0, f) {
494
+ if (!this.toColor)
495
+ this.toColor = this.getColor();
496
+ const diff = newColor.diff(this.toColor);
497
+ const finalColor = newColor.clone();
498
+ return transitionValues((p) => {
499
+ this.toColor.r += diff.r * p;
500
+ this.toColor.g += diff.g * p;
501
+ this.toColor.b += diff.b * p;
502
+ this.toColor.a += diff.a * p;
503
+ this.vertexCache.updated();
504
+ }, () => {
505
+ this.toColor = finalColor;
506
+ this.vertexCache.updated();
507
+ }, t, f);
508
+ }
509
+ setStart(pos, t = 0, f) {
510
+ return this.moveTo(vector3FromVector2(pos), t, f);
511
+ }
512
+ setEnd(pos, t = 0, f) {
513
+ const diff = vector3();
514
+ vec2.sub(pos, this.to, diff);
515
+ return transitionValues((p) => {
516
+ this.to[0] += diff[0] * p;
517
+ this.to[1] += diff[1] * p;
518
+ this.vertexCache.updated();
519
+ }, () => {
520
+ this.to[0] = pos[0];
521
+ this.to[1] = pos[1];
522
+ this.vertexCache.updated();
523
+ }, t, f);
524
+ }
525
+ getBuffer(camera, force) {
526
+ if (this.vertexCache.shouldUpdate() || force) {
527
+ const normal = vector2(-this.to[1], this.to[0]);
528
+ vec2.normalize(normal, normal);
529
+ vec2.scale(normal, this.thickness / 2, normal);
530
+ const screenSize = camera.getScreenSize();
531
+ const pos = this.getPos();
532
+ const resBuffer = [
533
+ ...vertexBuffer2d(pos[0] + normal[0], screenSize[1] - pos[1] + normal[1], this.getColor()),
534
+ ...vertexBuffer2d(pos[0] - normal[0], screenSize[1] - pos[1] - normal[1], this.getColor()),
535
+ ...vertexBuffer2d(pos[0] + this.to[0] + normal[0], screenSize[1] - pos[1] + this.to[1] + normal[1], this.toColor || this.getColor()),
536
+ ...vertexBuffer2d(pos[0] - normal[0], screenSize[1] - pos[1] - normal[1], this.getColor()),
537
+ ...vertexBuffer2d(pos[0] + this.to[0] + normal[0], screenSize[1] - pos[1] + this.to[1] + normal[1], this.toColor || this.getColor()),
538
+ ...vertexBuffer2d(pos[0] + this.to[0] - normal[0], screenSize[1] - pos[1] + this.to[1] - normal[1], this.toColor || this.getColor())
539
+ ];
540
+ this.vertexCache.setCache(resBuffer);
541
+ return resBuffer;
542
+ }
543
+ return this.vertexCache.getCache();
544
+ }
545
+ }
546
+ export class Cube extends SimulationElement {
547
+ vertices;
548
+ rotation;
549
+ width;
550
+ height;
551
+ depth;
552
+ wireframe;
553
+ wireframeLines;
554
+ static wireframeOrder = [
555
+ [0, 1],
556
+ [1, 2],
557
+ [2, 3],
558
+ [3, 0],
559
+ [4, 5],
560
+ [5, 6],
561
+ [6, 7],
562
+ [7, 4],
563
+ [0, 4],
564
+ [3, 7],
565
+ [1, 5],
566
+ [2, 6]
567
+ ];
568
+ constructor(pos, width, height, depth, color, rotation) {
569
+ super(pos, color);
570
+ this.width = width * devicePixelRatio;
571
+ this.height = height * devicePixelRatio;
572
+ this.depth = depth * devicePixelRatio;
573
+ this.rotation = rotation || vector3();
574
+ this.wireframe = false;
575
+ this.wireframeLines = [];
576
+ const numWireframeLines = 12;
577
+ const lineThickness = 0.025;
578
+ for (let i = 0; i < numWireframeLines; i++) {
579
+ this.wireframeLines.push(new Line3d(vertex(), vertex(), lineThickness));
580
+ }
581
+ this.vertices = [];
582
+ this.computeVertices();
583
+ this.shiftWireframeLines();
584
+ }
585
+ computeVertices() {
586
+ console.log(this.width, this.height);
587
+ this.vertices = [
588
+ // front face
589
+ vector3(-this.width / 2, -this.height / 2, this.depth / 2),
590
+ vector3(this.width / 2, -this.height / 2, this.depth / 2),
591
+ vector3(this.width / 2, this.height / 2, this.depth / 2),
592
+ vector3(-this.width / 2, this.height / 2, this.depth / 2),
593
+ // back face
594
+ vector3(-this.width / 2, -this.height / 2, -this.depth / 2),
595
+ vector3(this.width / 2, -this.height / 2, -this.depth / 2),
596
+ vector3(this.width / 2, this.height / 2, -this.depth / 2),
597
+ vector3(-this.width / 2, this.height / 2, -this.depth / 2)
598
+ ];
599
+ }
600
+ shiftWireframeLines() {
601
+ let rotMatrix = mat4.identity();
602
+ mat4.rotateZ(rotMatrix, this.rotation[2], rotMatrix);
603
+ mat4.rotateY(rotMatrix, this.rotation[1], rotMatrix);
604
+ mat4.rotateX(rotMatrix, this.rotation[0], rotMatrix);
605
+ const pos = this.getPos();
606
+ Cube.wireframeOrder.forEach((lineVertices, index) => {
607
+ const line = this.wireframeLines[index];
608
+ const start = cloneBuf(this.vertices[lineVertices[0]]);
609
+ const endPoint = cloneBuf(this.vertices[lineVertices[1]]);
610
+ vec3.sub(endPoint, start, endPoint);
611
+ vec3.transformMat4(endPoint, rotMatrix, endPoint);
612
+ vec3.transformMat4(start, rotMatrix, start);
613
+ vec3.add(start, pos, start);
614
+ line.setStart(start);
615
+ line.setEnd(endPoint);
616
+ });
617
+ }
618
+ setWireframe(wireframe) {
619
+ this.wireframe = wireframe;
620
+ }
621
+ rotate(amount, t = 0, f) {
622
+ const finalRotation = cloneBuf(this.rotation);
623
+ vec3.add(finalRotation, amount, finalRotation);
624
+ return transitionValues((p) => {
625
+ this.rotation[0] += amount[0] * p;
626
+ this.rotation[1] += amount[1] * p;
627
+ this.rotation[2] += amount[2] * p;
628
+ this.vertexCache.updated();
629
+ }, () => {
630
+ this.rotation = finalRotation;
631
+ this.vertexCache.updated();
632
+ }, t, f);
633
+ }
634
+ setRotation(rot, t = 0, f) {
635
+ const diff = vector3();
636
+ vec3.sub(rot, this.rotation, diff);
637
+ return transitionValues((p) => {
638
+ this.rotation[0] += diff[0] * p;
639
+ this.rotation[1] += diff[1] * p;
640
+ this.rotation[2] += diff[2] * p;
641
+ this.vertexCache.updated();
642
+ }, () => {
643
+ this.rotation = rot;
644
+ this.vertexCache.updated();
645
+ }, t, f);
646
+ }
647
+ setWidth(width, t = 0, f) {
648
+ width *= devicePixelRatio;
649
+ const diff = width - this.width;
650
+ return transitionValues((p) => {
651
+ this.width += diff * p;
652
+ this.vertexCache.updated();
653
+ }, () => {
654
+ this.width = width;
655
+ this.vertexCache.updated();
656
+ }, t, f);
657
+ }
658
+ setHeight(height, t = 0, f) {
659
+ height *= devicePixelRatio;
660
+ const diff = height - this.width;
661
+ return transitionValues((p) => {
662
+ this.height += diff * p;
663
+ this.vertexCache.updated();
664
+ }, () => {
665
+ this.height = height;
666
+ this.vertexCache.updated();
667
+ }, t, f);
668
+ }
669
+ setDepth(depth, t = 0, f) {
670
+ depth *= devicePixelRatio;
671
+ const diff = depth - this.width;
672
+ return transitionValues((p) => {
673
+ this.depth += diff * p;
674
+ this.vertexCache.updated();
675
+ }, () => {
676
+ this.depth = depth;
677
+ this.vertexCache.updated();
678
+ }, t, f);
679
+ }
680
+ scale(amount, t = 0, f) {
681
+ const finalWidth = this.width * amount;
682
+ const finalHeight = this.height * amount;
683
+ const finalDepth = this.depth * amount;
684
+ const widthDiff = finalWidth - this.width;
685
+ const heightDiff = finalHeight - this.height;
686
+ const depthDiff = finalDepth - this.depth;
687
+ return transitionValues((p) => {
688
+ this.width += widthDiff * p;
689
+ this.height += heightDiff * p;
690
+ this.depth += depthDiff * p;
691
+ this.vertexCache.updated();
692
+ }, () => {
693
+ this.width = finalWidth;
694
+ this.height = finalHeight;
695
+ this.depth = finalDepth;
696
+ this.vertexCache.updated();
697
+ }, t, f);
698
+ }
699
+ getBuffer(camera, force) {
700
+ if (this.vertexCache.shouldUpdate() || force) {
701
+ this.computeVertices();
702
+ this.shiftWireframeLines();
703
+ const triangleOrder = [
704
+ 0, 1, 2, 0, 2, 3,
705
+ 4, 5, 6, 4, 6, 7,
706
+ 0, 3, 7, 0, 7, 4,
707
+ 0, 4, 5, 0, 5, 1,
708
+ 1, 2, 6, 1, 5, 6,
709
+ 2, 3, 7, 2, 6, 7
710
+ ];
711
+ let rotMatrix = mat4.identity();
712
+ mat4.rotateZ(rotMatrix, this.rotation[2], rotMatrix);
713
+ mat4.rotateY(rotMatrix, this.rotation[1], rotMatrix);
714
+ mat4.rotateX(rotMatrix, this.rotation[0], rotMatrix);
715
+ const pos = this.getPos();
716
+ let resBuffer = [];
717
+ triangleOrder.forEach((index) => {
718
+ const vertex = cloneBuf(this.vertices[index]);
719
+ vec3.transformMat4(vertex, rotMatrix, vertex);
720
+ resBuffer = resBuffer.concat(vertexBuffer3d(vertex[0] + pos[0], vertex[1] + pos[1], vertex[2] + pos[2], this.getColor()));
721
+ });
722
+ if (this.wireframe) {
723
+ this.wireframeLines.forEach((line) => {
724
+ resBuffer = resBuffer.concat(line.getBuffer(camera, force));
725
+ });
726
+ }
727
+ this.vertexCache.setCache(resBuffer);
728
+ return resBuffer;
729
+ }
730
+ return this.vertexCache.getCache();
731
+ }
732
+ }
434
733
  export class BezierCurve2d {
435
734
  points;
436
735
  constructor(points) {
@@ -524,14 +823,18 @@ export class SplinePoint2d {
524
823
  return this.detail;
525
824
  }
526
825
  getColors(prevColor) {
527
- const colors = [];
528
- if (prevColor)
529
- colors.push(prevColor);
826
+ const colors = [null, null];
530
827
  if (this.start && this.start.getColor()) {
531
- colors.push(this.start.getColor());
828
+ colors[0] = this.start.getColor();
532
829
  }
533
830
  if (this.end.getColor()) {
534
- colors.push(this.end.getColor());
831
+ colors[1] = this.end.getColor();
832
+ }
833
+ if (prevColor) {
834
+ colors.unshift(prevColor);
835
+ }
836
+ if (colors.at(-1) === null) {
837
+ colors.pop();
535
838
  }
536
839
  return colors;
537
840
  }
@@ -553,26 +856,26 @@ export class SplinePoint2d {
553
856
  }
554
857
  export class Spline2d extends SimulationElement {
555
858
  curves;
556
- width;
859
+ thickness;
557
860
  detail;
558
861
  interpolateLimit;
559
862
  distance;
560
- constructor(pos, points, width = 2, detail = 40) {
863
+ constructor(pos, points, thickness = devicePixelRatio, detail = 40) {
561
864
  super(pos.getPos(), pos.getColor() || undefined);
562
865
  this.curves = [];
563
- this.width = width * devicePixelRatio;
866
+ this.thickness = thickness * devicePixelRatio;
564
867
  this.detail = detail;
565
868
  this.interpolateLimit = 1;
566
869
  this.distance = 0;
567
870
  for (let i = 0; i < points.length; i++) {
568
871
  let prevControl = null;
569
- let prevColor = this.getColor();
872
+ let prevColor = null;
570
873
  if (i > 0) {
571
874
  prevControl = cloneBuf(points[i - 1].getRawControls()[1]);
572
875
  vec2.negate(prevControl, prevControl);
573
876
  const prevColors = points[i - 1].getColors();
574
877
  if (prevColors.at(-1)) {
575
- prevColor = prevColors.at(-1);
878
+ prevColor = prevColors.at(-1) || null;
576
879
  }
577
880
  }
578
881
  const bezierPoints = points[i].getVectorArray(i > 0 ? vector2FromVector3(points[i - 1].getEnd().getPos()) : null, prevControl);
@@ -619,8 +922,9 @@ export class Spline2d extends SimulationElement {
619
922
  point[1] += screenSize[1] - pos[1];
620
923
  const normal = vector2(-slope[1], slope[0]);
621
924
  vec2.normalize(normal, normal);
622
- vec2.scale(normal, this.width / 2, normal);
623
- const vertexColor = interpolateColors(this.curves[i].getColors(), currentInterpolation);
925
+ vec2.scale(normal, this.thickness / 2, normal);
926
+ const colors = this.curves[i].getColors().map((c) => (c ? c : this.getColor()));
927
+ const vertexColor = interpolateColors(colors, currentInterpolation);
624
928
  const vertTop = vertex(point[0] + normal[0], point[1] + normal[1], 0, vertexColor);
625
929
  verticesTop.push(vertTop);
626
930
  const vertBottom = vertex(point[0] - normal[0], point[1] - normal[1], 0, vertexColor);
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 } from './utils.js';
4
+ export { Vertex, Color, cloneBuf, vector4, vector3, vector2, vector3FromVector2, colorFromVector4, randomInt, randomColor, vertex, color, colorf, transitionValues, lerp, smoothStep, linearStep, exponentialStep, splinePoint2d, continuousSplinePoint2d } 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 } from './utils.js';
4
+ export { Vertex, Color, cloneBuf, vector4, vector3, vector2, vector3FromVector2, colorFromVector4, randomInt, randomColor, vertex, color, colorf, transitionValues, lerp, smoothStep, linearStep, exponentialStep, splinePoint2d, continuousSplinePoint2d } from './utils.js';
@@ -11,7 +11,7 @@ export declare class Simulation {
11
11
  private frameRateView;
12
12
  private camera;
13
13
  constructor(idOrCanvasRef: string | HTMLCanvasElement, camera?: Camera | null, showFrameRate?: boolean);
14
- add(el: SimulationElement): void;
14
+ add(el: SimulationElement<any>): void;
15
15
  setCanvasSize(width: number, height: number): void;
16
16
  start(): void;
17
17
  stop(): void;
@@ -1,7 +1,7 @@
1
1
  import { vec3 } from 'wgpu-matrix';
2
2
  import { SimulationElement } from './graphics.js';
3
3
  import { BUF_LEN } from './constants.js';
4
- import { Color, applyElementToScene, buildMultisampleTexture, buildProjectionMatrix, getOrthoMatrix, getTransformationMatrix, logger, transitionValues, vector2, vector3 } from './utils.js';
4
+ import { Color, applyElementToScene, buildDepthTexture, buildMultisampleTexture, buildProjectionMatrix, getOrthoMatrix, getTransformationMatrix, logger, transitionValues, vector2, vector3 } from './utils.js';
5
5
  const vertexSize = 44; // 4 * 10 + 1
6
6
  const colorOffset = 16; // 4 * 4
7
7
  const uvOffset = 32; // 4 * 8
@@ -229,6 +229,11 @@ export class Simulation {
229
229
  },
230
230
  multisample: {
231
231
  count: 4
232
+ },
233
+ depthStencil: {
234
+ depthWriteEnabled: true,
235
+ depthCompare: 'less',
236
+ format: 'depth24plus'
232
237
  }
233
238
  });
234
239
  const uniformBufferSize = 4 * 16 + 4 * 16 + 4 * 2 + 8; // 4x4 matrix + 4x4 matrix + vec2<f32> + 8 bc 144 is cool
@@ -267,8 +272,15 @@ export class Simulation {
267
272
  };
268
273
  updateOrthoMatrix();
269
274
  let multisampleTexture = buildMultisampleTexture(device, ctx, canvas.width, canvas.height);
275
+ let depthTexture = buildDepthTexture(device, canvas.width, canvas.height);
270
276
  const renderPassDescriptor = {
271
- colorAttachments: [colorAttachment]
277
+ colorAttachments: [colorAttachment],
278
+ depthStencilAttachment: {
279
+ view: depthTexture.createView(),
280
+ depthClearValue: 1.0,
281
+ depthLoadOp: 'clear',
282
+ depthStoreOp: 'store'
283
+ }
272
284
  };
273
285
  // sub 10 to start with a reasonable gap between starting time and next frame time
274
286
  let prev = Date.now() - 10;
@@ -296,6 +308,8 @@ export class Simulation {
296
308
  projectionMatrix = buildProjectionMatrix(aspect);
297
309
  updateModelViewProjectionMatrix();
298
310
  multisampleTexture = buildMultisampleTexture(device, ctx, screenSize[0], screenSize[1]);
311
+ depthTexture = buildDepthTexture(device, screenSize[0], screenSize[1]);
312
+ renderPassDescriptor.depthStencilAttachment.view = depthTexture.createView();
299
313
  }
300
314
  // @ts-ignore
301
315
  renderPassDescriptor.colorAttachments[0].view = multisampleTexture.createView();
package/dist/utils.d.ts CHANGED
@@ -51,6 +51,7 @@ export declare class Vertex {
51
51
  export declare const buildProjectionMatrix: (aspectRatio: number, zNear?: number, zFar?: number) => any;
52
52
  export declare const getTransformationMatrix: (pos: Vector3, rotation: Vector3, projectionMatrix: mat4) => Float32Array;
53
53
  export declare const getOrthoMatrix: (screenSize: [number, number]) => Float32Array;
54
+ export declare const buildDepthTexture: (device: GPUDevice, width: number, height: number) => GPUTexture;
54
55
  export declare const buildMultisampleTexture: (device: GPUDevice, ctx: GPUCanvasContext, width: number, height: number) => GPUTexture;
55
56
  export declare const applyElementToScene: (scene: SimulationElement[], camera: Camera | null, el: SimulationElement) => void;
56
57
  declare class Logger {
@@ -72,7 +73,8 @@ export declare function lossyTriangulate(vertices: Vertex[]): (readonly [Vertex,
72
73
  export declare function transitionValues(callback1: (deltaT: number, t: number) => void, callback2: () => void, transitionLength: number, func?: (n: number) => number): Promise<void>;
73
74
  export declare function lerp(a: number, b: number, t: number): number;
74
75
  export declare function smoothStep(t: number): number;
75
- export declare function linearStep(n: number): number;
76
+ export declare function linearStep(t: number): number;
77
+ export declare function exponentialStep(t: number): number;
76
78
  export declare function vertexBuffer3d(x: number, y: number, z: number, color: Color, uv?: Vector2): number[];
77
79
  export declare function vertexBuffer2d(x: number, y: number, color: Color, uv?: Vector2): number[];
78
80
  export declare function vec3ToPixelRatio(vec: Vector3): void;
package/dist/utils.js CHANGED
@@ -125,6 +125,14 @@ export const getTransformationMatrix = (pos, rotation, projectionMatrix) => {
125
125
  export const getOrthoMatrix = (screenSize) => {
126
126
  return mat4.ortho(0, screenSize[0], 0, screenSize[1], 0, 100);
127
127
  };
128
+ export const buildDepthTexture = (device, width, height) => {
129
+ return device.createTexture({
130
+ size: [width, height],
131
+ format: 'depth24plus',
132
+ usage: GPUTextureUsage.RENDER_ATTACHMENT,
133
+ sampleCount: 4
134
+ });
135
+ };
128
136
  export const buildMultisampleTexture = (device, ctx, width, height) => {
129
137
  return device.createTexture({
130
138
  size: [width, height],
@@ -237,8 +245,17 @@ export function smoothStep(t) {
237
245
  const v2 = 1 - (1 - t) * (1 - t);
238
246
  return lerp(v1, v2, t);
239
247
  }
240
- export function linearStep(n) {
241
- return n;
248
+ export function linearStep(t) {
249
+ return t;
250
+ }
251
+ export function exponentialStep(t) {
252
+ return t === 0
253
+ ? 0
254
+ : t === 1
255
+ ? 1
256
+ : t < 0.5
257
+ ? Math.pow(2, 20 * t - 10) / 2
258
+ : (2 - Math.pow(2, -20 * t + 10)) / 2;
242
259
  }
243
260
  export function vertexBuffer3d(x, y, z, color, uv = vector2()) {
244
261
  return [x, y, z, 1, ...color.toBuffer(), ...uv, 1];
@@ -301,6 +318,10 @@ export function continuousSplinePoint2d(end, control, detail) {
301
318
  return new SplinePoint2d(null, end, null, control, rawControls, detail);
302
319
  }
303
320
  export function interpolateColors(colors, t) {
321
+ if (colors.length === 0)
322
+ return color();
323
+ if (colors.length === 1)
324
+ return colors[0];
304
325
  const colorInterval = 1 / colors.length;
305
326
  let index = Math.floor(t / colorInterval);
306
327
  if (index === colors.length)
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.9",
8
+ "version": "0.2.0",
9
9
  "exports": {
10
10
  ".": {
11
11
  "import": "./dist/index.js",