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.
- package/dist/graphics.d.ts +55 -15
- package/dist/graphics.js +338 -34
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/simulation.d.ts +1 -1
- package/dist/simulation.js +16 -2
- package/dist/utils.d.ts +3 -1
- package/dist/utils.js +23 -2
- package/package.json +1 -1
package/dist/graphics.d.ts
CHANGED
|
@@ -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:
|
|
10
|
-
setPos(pos:
|
|
11
|
-
getPos():
|
|
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:
|
|
16
|
-
moveTo(pos:
|
|
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:
|
|
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
|
|
138
|
+
private thickness;
|
|
99
139
|
private detail;
|
|
100
140
|
private interpolateLimit;
|
|
101
141
|
private distance;
|
|
102
|
-
constructor(pos: Vertex, points: SplinePoint2d[],
|
|
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
|
|
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 +=
|
|
32
|
-
this.color.g +=
|
|
33
|
-
this.color.b +=
|
|
34
|
-
this.color.a +=
|
|
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 =
|
|
42
|
+
const finalPos = amount.length === 3 ? vector3() : vector2();
|
|
46
43
|
vec3.add(finalPos, this.pos, amount);
|
|
47
44
|
return transitionValues((p) => {
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
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 =
|
|
55
|
+
const diff = pos.length === 3 ? vector3() : vector2();
|
|
60
56
|
vec3.sub(diff, pos, this.pos);
|
|
61
57
|
return transitionValues((p) => {
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
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
|
|
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(
|
|
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(
|
|
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
|
|
828
|
+
colors[0] = this.start.getColor();
|
|
532
829
|
}
|
|
533
830
|
if (this.end.getColor()) {
|
|
534
|
-
colors
|
|
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
|
-
|
|
859
|
+
thickness;
|
|
557
860
|
detail;
|
|
558
861
|
interpolateLimit;
|
|
559
862
|
distance;
|
|
560
|
-
constructor(pos, points,
|
|
863
|
+
constructor(pos, points, thickness = devicePixelRatio, detail = 40) {
|
|
561
864
|
super(pos.getPos(), pos.getColor() || undefined);
|
|
562
865
|
this.curves = [];
|
|
563
|
-
this.
|
|
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 =
|
|
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.
|
|
623
|
-
const
|
|
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';
|
package/dist/simulation.d.ts
CHANGED
|
@@ -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;
|
package/dist/simulation.js
CHANGED
|
@@ -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(
|
|
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(
|
|
241
|
-
return
|
|
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)
|