simulationjsv2 0.2.9 → 0.3.1
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/geometry.d.ts +7 -5
- package/dist/geometry.js +17 -8
- package/dist/graphics.d.ts +12 -5
- package/dist/graphics.js +69 -21
- package/dist/index.d.ts +2 -1
- package/dist/index.js +2 -1
- package/dist/internalUtils.d.ts +46 -0
- package/dist/internalUtils.js +258 -0
- package/dist/simulation.js +2 -1
- package/dist/types.d.ts +3 -1
- package/dist/utils.d.ts +5 -45
- package/dist/utils.js +27 -254
- package/package.json +2 -2
package/dist/geometry.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { CircleGeometryParams, CubeGeometryParams, Line2dGeometryParams, Line3dGeometryParams, Mat4, PolygonGeometryParams,
|
|
1
|
+
import { CircleGeometryParams, CubeGeometryParams, Line2dGeometryParams, Line3dGeometryParams, Mat4, PolygonGeometryParams, Spline2dGeometryParams, SquareGeometryParams, Vector2, Vector3, VertexColorMap } from './types.js';
|
|
2
2
|
import { Color, Vertex } from './utils.js';
|
|
3
|
-
import { SplinePoint2d } from './graphics.js';
|
|
3
|
+
import { CubicBezierCurve2d, SplinePoint2d } from './graphics.js';
|
|
4
4
|
export declare abstract class Geometry {
|
|
5
5
|
protected abstract wireframeOrder: number[];
|
|
6
6
|
protected abstract triangleOrder: number[];
|
|
@@ -43,7 +43,7 @@ export declare class SquareGeometry extends Geometry {
|
|
|
43
43
|
protected wireframeOrder: number[];
|
|
44
44
|
protected triangleOrder: number[];
|
|
45
45
|
protected params: SquareGeometryParams;
|
|
46
|
-
constructor(width: number, height: number);
|
|
46
|
+
constructor(width: number, height: number, centerOffset?: Vector2);
|
|
47
47
|
setVertexColorMap(colorMap: VertexColorMap): void;
|
|
48
48
|
setWidth(width: number): void;
|
|
49
49
|
setHeight(height: number): void;
|
|
@@ -67,16 +67,18 @@ export declare class CircleGeometry extends Geometry {
|
|
|
67
67
|
private updateTriangleOrder;
|
|
68
68
|
recompute(): void;
|
|
69
69
|
}
|
|
70
|
-
export declare class
|
|
70
|
+
export declare class Spline2dGeometry extends Geometry {
|
|
71
71
|
protected wireframeOrder: number[];
|
|
72
72
|
protected triangleOrder: number[];
|
|
73
|
-
protected params:
|
|
73
|
+
protected params: Spline2dGeometryParams;
|
|
74
74
|
constructor(points: SplinePoint2d[], color: Color, thickness: number, detail: number);
|
|
75
75
|
updateInterpolationStart(start: number): void;
|
|
76
76
|
updateInterpolationLimit(limit: number): void;
|
|
77
|
+
updateThickness(thickness: number): void;
|
|
77
78
|
private getVertexCount;
|
|
78
79
|
getWireframeVertexCount(): number;
|
|
79
80
|
getTriangleVertexCount(): number;
|
|
81
|
+
getCurves(): CubicBezierCurve2d[];
|
|
80
82
|
private computeCurves;
|
|
81
83
|
private updateWireframeOrder;
|
|
82
84
|
recompute(): void;
|
package/dist/geometry.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { mat4, vec2, vec3 } from 'wgpu-matrix';
|
|
2
|
-
import { cloneBuf,
|
|
2
|
+
import { cloneBuf, matrix4, vector2, vector2FromVector3, vector3, vector3FromVector2, vertex } from './utils.js';
|
|
3
3
|
import { CubicBezierCurve2d } from './graphics.js';
|
|
4
4
|
import { BUF_LEN } from './constants.js';
|
|
5
|
+
import { bufferGenerator, interpolateColors, lossyTriangulate, triangulateWireFrameOrder } from './internalUtils.js';
|
|
5
6
|
export class Geometry {
|
|
6
7
|
vertices;
|
|
7
8
|
matrix;
|
|
@@ -126,12 +127,13 @@ export class SquareGeometry extends Geometry {
|
|
|
126
127
|
wireframeOrder = [0, 1, 2, 3, 0, 2];
|
|
127
128
|
triangleOrder = [0, 1, 3, 2];
|
|
128
129
|
params;
|
|
129
|
-
constructor(width, height) {
|
|
130
|
+
constructor(width, height, centerOffset) {
|
|
130
131
|
super([], 'strip');
|
|
131
132
|
this.params = {
|
|
132
133
|
width,
|
|
133
134
|
height,
|
|
134
|
-
colorMap: {}
|
|
135
|
+
colorMap: {},
|
|
136
|
+
centerOffset: centerOffset || vector2(0, 0)
|
|
135
137
|
};
|
|
136
138
|
this.recompute();
|
|
137
139
|
}
|
|
@@ -145,11 +147,12 @@ export class SquareGeometry extends Geometry {
|
|
|
145
147
|
this.params.height = height;
|
|
146
148
|
}
|
|
147
149
|
recompute() {
|
|
150
|
+
const centerOffset = this.params.centerOffset;
|
|
148
151
|
this.vertices = [
|
|
149
|
-
vector3(-this.params.width
|
|
150
|
-
vector3(this.params.width
|
|
151
|
-
vector3(this.params.width
|
|
152
|
-
vector3(-this.params.width
|
|
152
|
+
vector3(-this.params.width * centerOffset[0], this.params.height * centerOffset[1]),
|
|
153
|
+
vector3(this.params.width * (1 - centerOffset[0]), this.params.height * centerOffset[1]),
|
|
154
|
+
vector3(this.params.width * (1 - centerOffset[0]), -this.params.height * (1 - centerOffset[1])),
|
|
155
|
+
vector3(-this.params.width * centerOffset[0], -this.params.height * (1 - centerOffset[1]))
|
|
153
156
|
];
|
|
154
157
|
}
|
|
155
158
|
getTriangleBuffer(color) {
|
|
@@ -208,7 +211,7 @@ export class CircleGeometry extends Geometry {
|
|
|
208
211
|
this.updateWireframeOrder();
|
|
209
212
|
}
|
|
210
213
|
}
|
|
211
|
-
export class
|
|
214
|
+
export class Spline2dGeometry extends Geometry {
|
|
212
215
|
wireframeOrder;
|
|
213
216
|
triangleOrder;
|
|
214
217
|
params;
|
|
@@ -236,6 +239,9 @@ export class SplineGeometry extends Geometry {
|
|
|
236
239
|
updateInterpolationLimit(limit) {
|
|
237
240
|
this.params.interpolateLimit = Math.min(1, Math.max(0, limit));
|
|
238
241
|
}
|
|
242
|
+
updateThickness(thickness) {
|
|
243
|
+
this.params.thickness = thickness;
|
|
244
|
+
}
|
|
239
245
|
getVertexCount() {
|
|
240
246
|
return this.triangleOrder.length * BUF_LEN;
|
|
241
247
|
}
|
|
@@ -245,6 +251,9 @@ export class SplineGeometry extends Geometry {
|
|
|
245
251
|
getTriangleVertexCount() {
|
|
246
252
|
return this.getVertexCount();
|
|
247
253
|
}
|
|
254
|
+
getCurves() {
|
|
255
|
+
return this.params.curves;
|
|
256
|
+
}
|
|
248
257
|
computeCurves() {
|
|
249
258
|
for (let i = 0; i < this.params.points.length; i++) {
|
|
250
259
|
let prevControl = null;
|
package/dist/graphics.d.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
/// <reference types="dist" />
|
|
2
2
|
import { Camera } from './simulation.js';
|
|
3
3
|
import type { Vector2, Vector3, LerpFunc, VertexColorMap, ElementRotation, Mat4 } from './types.js';
|
|
4
|
-
import { Vertex,
|
|
5
|
-
import { BlankGeometry, CircleGeometry, CubeGeometry, Geometry, Line2dGeometry, Line3dGeometry, PlaneGeometry, PolygonGeometry,
|
|
4
|
+
import { Vertex, Color } from './utils.js';
|
|
5
|
+
import { BlankGeometry, CircleGeometry, CubeGeometry, Geometry, Line2dGeometry, Line3dGeometry, PlaneGeometry, PolygonGeometry, Spline2dGeometry, SquareGeometry } from './geometry.js';
|
|
6
|
+
import { VertexCache } from './internalUtils.js';
|
|
6
7
|
export declare abstract class SimulationElement<T extends Vector2 | Vector3 = Vector3> {
|
|
7
8
|
protected abstract pos: T;
|
|
8
9
|
protected abstract geometry: Geometry;
|
|
@@ -63,9 +64,10 @@ export declare class Square extends SimulationElement2d {
|
|
|
63
64
|
private height;
|
|
64
65
|
private vertexColors;
|
|
65
66
|
/**
|
|
67
|
+
* @param centerOffset{Vector2} - A vector2 of values from 0 to 1
|
|
66
68
|
* @param vertexColors{Record<number, Color>} - 0 is top left vertex, numbers increase clockwise
|
|
67
69
|
*/
|
|
68
|
-
constructor(pos: Vector2, width: number, height: number, color?: Color, rotation?: number, vertexColors?: VertexColorMap);
|
|
70
|
+
constructor(pos: Vector2, width: number, height: number, color?: Color, rotation?: number, centerOffset?: Vector2, vertexColors?: VertexColorMap);
|
|
69
71
|
private cloneColorMap;
|
|
70
72
|
setVertexColors(newColorMap: VertexColorMap, t?: number, f?: LerpFunc): Promise<void>;
|
|
71
73
|
scaleWidth(amount: number, t?: number, f?: LerpFunc): Promise<void>;
|
|
@@ -124,10 +126,12 @@ export declare class Cube extends SimulationElement3d {
|
|
|
124
126
|
}
|
|
125
127
|
export declare class BezierCurve2d {
|
|
126
128
|
private points;
|
|
129
|
+
private length;
|
|
127
130
|
constructor(points: Vector2[]);
|
|
128
131
|
interpolateSlope(t: number): readonly [Vector2, Vector2];
|
|
129
132
|
interpolate(t: number): Vector2;
|
|
130
133
|
getPoints(): Vector2[];
|
|
134
|
+
estimateLength(detail: number): number;
|
|
131
135
|
getLength(): number;
|
|
132
136
|
}
|
|
133
137
|
export declare class CubicBezierCurve2d extends BezierCurve2d {
|
|
@@ -154,15 +158,18 @@ export declare class SplinePoint2d {
|
|
|
154
158
|
getVectorArray(prevEnd: Vector2 | null, prevControl: Vector2 | null): readonly [Vector2, Vector2, Vector2, Vector2];
|
|
155
159
|
}
|
|
156
160
|
export declare class Spline2d extends SimulationElement2d {
|
|
157
|
-
protected geometry:
|
|
158
|
-
private curves;
|
|
161
|
+
protected geometry: Spline2dGeometry;
|
|
159
162
|
private thickness;
|
|
160
163
|
private detail;
|
|
161
164
|
private interpolateStart;
|
|
162
165
|
private interpolateLimit;
|
|
166
|
+
private length;
|
|
163
167
|
constructor(pos: Vertex, points: SplinePoint2d[], thickness?: number, detail?: number);
|
|
168
|
+
private estimateLength;
|
|
169
|
+
getLength(): number;
|
|
164
170
|
setInterpolateStart(start: number, t?: number, f?: LerpFunc): Promise<void>;
|
|
165
171
|
setInterpolateLimit(limit: number, t?: number, f?: LerpFunc): Promise<void>;
|
|
172
|
+
setThickness(thickness: number, t?: number, f?: LerpFunc): Promise<void>;
|
|
166
173
|
interpolateSlope(t: number): readonly [Vector2, Vector2];
|
|
167
174
|
interpolate(t: number): Vector2;
|
|
168
175
|
protected updateMatrix(camera: Camera): void;
|
package/dist/graphics.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { vec3, mat4, vec2, vec4 } from 'wgpu-matrix';
|
|
2
|
-
import { Vertex,
|
|
3
|
-
import { BlankGeometry, CircleGeometry, CubeGeometry, Line2dGeometry, Line3dGeometry, PlaneGeometry, PolygonGeometry,
|
|
2
|
+
import { Vertex, cloneBuf, color, colorFromVector4, vector2, vector3, vertex, Color, transitionValues, vector2FromVector3, matrix4, vector3FromVector2, distance2d } from './utils.js';
|
|
3
|
+
import { BlankGeometry, CircleGeometry, CubeGeometry, Line2dGeometry, Line3dGeometry, PlaneGeometry, PolygonGeometry, Spline2dGeometry, SquareGeometry } from './geometry.js';
|
|
4
|
+
import { VertexCache, bufferGenerator, logger, rotateMat4, vector2ToPixelRatio, vector3ToPixelRatio } from './internalUtils.js';
|
|
4
5
|
export class SimulationElement {
|
|
5
6
|
color;
|
|
6
7
|
wireframe;
|
|
@@ -62,7 +63,7 @@ export class SimulationElement {
|
|
|
62
63
|
const matrix = matrix4();
|
|
63
64
|
if (typeof this.rotation === 'number') {
|
|
64
65
|
const pos = vector3FromVector2(this.pos);
|
|
65
|
-
pos[1] = camera.getScreenSize()[1]
|
|
66
|
+
pos[1] = camera.getScreenSize()[1] + pos[1];
|
|
66
67
|
mat4.translate(matrix, pos, matrix);
|
|
67
68
|
mat4.rotateZ(matrix, this.rotation, matrix);
|
|
68
69
|
}
|
|
@@ -232,15 +233,16 @@ export class Square extends SimulationElement2d {
|
|
|
232
233
|
height;
|
|
233
234
|
vertexColors;
|
|
234
235
|
/**
|
|
236
|
+
* @param centerOffset{Vector2} - A vector2 of values from 0 to 1
|
|
235
237
|
* @param vertexColors{Record<number, Color>} - 0 is top left vertex, numbers increase clockwise
|
|
236
238
|
*/
|
|
237
|
-
constructor(pos, width, height, color, rotation, vertexColors) {
|
|
239
|
+
constructor(pos, width, height, color, rotation, centerOffset, vertexColors) {
|
|
238
240
|
super(pos, rotation, color);
|
|
239
241
|
vector2ToPixelRatio(this.pos);
|
|
240
242
|
this.width = width * devicePixelRatio;
|
|
241
243
|
this.height = height * devicePixelRatio;
|
|
242
244
|
this.vertexColors = this.cloneColorMap(vertexColors || {});
|
|
243
|
-
this.geometry = new SquareGeometry(this.width, this.height);
|
|
245
|
+
this.geometry = new SquareGeometry(this.width, this.height, centerOffset);
|
|
244
246
|
this.geometry.setVertexColorMap(this.vertexColors);
|
|
245
247
|
}
|
|
246
248
|
cloneColorMap(colorMap) {
|
|
@@ -358,9 +360,7 @@ export class Square extends SimulationElement2d {
|
|
|
358
360
|
}
|
|
359
361
|
updateMatrix(camera) {
|
|
360
362
|
const pos = cloneBuf(this.pos);
|
|
361
|
-
pos[1] = camera.getScreenSize()[1]
|
|
362
|
-
pos[0] += this.width / 2;
|
|
363
|
-
pos[1] -= this.height / 2;
|
|
363
|
+
pos[1] = camera.getScreenSize()[1] + pos[1];
|
|
364
364
|
const matrix = matrix4();
|
|
365
365
|
mat4.translate(matrix, vector3FromVector2(pos), matrix);
|
|
366
366
|
mat4.rotateZ(matrix, this.rotation, matrix);
|
|
@@ -638,10 +638,13 @@ export class Cube extends SimulationElement3d {
|
|
|
638
638
|
}
|
|
639
639
|
export class BezierCurve2d {
|
|
640
640
|
points;
|
|
641
|
+
length;
|
|
641
642
|
constructor(points) {
|
|
642
643
|
if (points.length === 0)
|
|
643
644
|
throw logger.error('Expected 1 or more points for BezierCurve2d');
|
|
644
645
|
this.points = points;
|
|
646
|
+
const dist = distance2d(points[0], points[points.length - 1]);
|
|
647
|
+
this.length = this.estimateLength(dist);
|
|
645
648
|
}
|
|
646
649
|
interpolateSlope(t) {
|
|
647
650
|
t = Math.max(0, Math.min(1, t));
|
|
@@ -678,10 +681,20 @@ export class BezierCurve2d {
|
|
|
678
681
|
getPoints() {
|
|
679
682
|
return this.points;
|
|
680
683
|
}
|
|
684
|
+
estimateLength(detail) {
|
|
685
|
+
let totalDist = 0;
|
|
686
|
+
for (let i = 0; i < detail - 1; i++) {
|
|
687
|
+
const t1 = i / detail;
|
|
688
|
+
const t2 = (i + 1) / detail;
|
|
689
|
+
const p1 = this.interpolate(t1);
|
|
690
|
+
const p2 = this.interpolate(t2);
|
|
691
|
+
const dist = distance2d(p1, p2);
|
|
692
|
+
totalDist += dist;
|
|
693
|
+
}
|
|
694
|
+
return totalDist;
|
|
695
|
+
}
|
|
681
696
|
getLength() {
|
|
682
|
-
|
|
683
|
-
const end = this.points[this.points.length - 1];
|
|
684
|
-
return Math.sqrt(Math.pow(end[0] - start[0], 2) + Math.pow(end[1] - start[1], 2));
|
|
697
|
+
return this.length;
|
|
685
698
|
}
|
|
686
699
|
}
|
|
687
700
|
export class CubicBezierCurve2d extends BezierCurve2d {
|
|
@@ -763,19 +776,31 @@ export class SplinePoint2d {
|
|
|
763
776
|
}
|
|
764
777
|
export class Spline2d extends SimulationElement2d {
|
|
765
778
|
geometry;
|
|
766
|
-
curves;
|
|
767
779
|
thickness;
|
|
768
780
|
detail;
|
|
769
781
|
interpolateStart;
|
|
770
782
|
interpolateLimit;
|
|
783
|
+
length;
|
|
771
784
|
constructor(pos, points, thickness = devicePixelRatio, detail = 40) {
|
|
772
|
-
|
|
773
|
-
|
|
785
|
+
const tempPos = vector2FromVector3(pos.getPos());
|
|
786
|
+
vector2ToPixelRatio(tempPos);
|
|
787
|
+
super(tempPos, 0, pos.getColor() || undefined);
|
|
774
788
|
this.thickness = thickness * devicePixelRatio;
|
|
775
789
|
this.detail = detail;
|
|
776
790
|
this.interpolateStart = 0;
|
|
777
791
|
this.interpolateLimit = 1;
|
|
778
|
-
this.
|
|
792
|
+
this.length = 0;
|
|
793
|
+
this.geometry = new Spline2dGeometry(points, this.getColor(), this.thickness, this.detail);
|
|
794
|
+
this.estimateLength();
|
|
795
|
+
}
|
|
796
|
+
estimateLength() {
|
|
797
|
+
const curves = this.geometry.getCurves();
|
|
798
|
+
for (let i = 0; i < curves.length; i++) {
|
|
799
|
+
this.length += curves[i].getLength();
|
|
800
|
+
}
|
|
801
|
+
}
|
|
802
|
+
getLength() {
|
|
803
|
+
return this.length;
|
|
779
804
|
}
|
|
780
805
|
setInterpolateStart(start, t = 0, f) {
|
|
781
806
|
const diff = start - this.interpolateStart;
|
|
@@ -801,13 +826,36 @@ export class Spline2d extends SimulationElement2d {
|
|
|
801
826
|
this.vertexCache.updated();
|
|
802
827
|
}, t, f);
|
|
803
828
|
}
|
|
829
|
+
setThickness(thickness, t = 0, f) {
|
|
830
|
+
thickness *= devicePixelRatio;
|
|
831
|
+
const diff = thickness - this.thickness;
|
|
832
|
+
return transitionValues((p) => {
|
|
833
|
+
this.thickness += diff * p;
|
|
834
|
+
this.geometry.updateThickness(this.thickness);
|
|
835
|
+
this.vertexCache.updated();
|
|
836
|
+
}, () => {
|
|
837
|
+
this.thickness = thickness;
|
|
838
|
+
this.geometry.updateThickness(this.thickness);
|
|
839
|
+
this.vertexCache.updated();
|
|
840
|
+
}, t, f);
|
|
841
|
+
}
|
|
804
842
|
interpolateSlope(t) {
|
|
805
|
-
const
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
843
|
+
const curves = this.geometry.getCurves();
|
|
844
|
+
const totalLength = this.length;
|
|
845
|
+
let currentLength = 0;
|
|
846
|
+
let index = 0;
|
|
847
|
+
let diff = 0;
|
|
848
|
+
for (let i = 0; i < curves.length; i++) {
|
|
849
|
+
if ((currentLength + curves[i].getLength()) / totalLength >= t) {
|
|
850
|
+
let dist = totalLength * t;
|
|
851
|
+
dist -= currentLength;
|
|
852
|
+
diff = dist / curves[i].getLength();
|
|
853
|
+
index = i;
|
|
854
|
+
break;
|
|
855
|
+
}
|
|
856
|
+
currentLength += curves[i].getLength();
|
|
857
|
+
}
|
|
858
|
+
return curves[index].interpolateSlope(diff);
|
|
811
859
|
}
|
|
812
860
|
interpolate(t) {
|
|
813
861
|
const [vec] = this.interpolateSlope(t);
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export * from './simulation.js';
|
|
2
2
|
export * from './graphics.js';
|
|
3
|
+
export * from './utils.js';
|
|
3
4
|
export * from './types.js';
|
|
4
|
-
export {
|
|
5
|
+
export { vec2, vec3, vec4, mat3, mat4 } from 'wgpu-matrix';
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export * from './simulation.js';
|
|
2
2
|
export * from './graphics.js';
|
|
3
|
+
export * from './utils.js';
|
|
3
4
|
export * from './types.js';
|
|
4
|
-
export {
|
|
5
|
+
export { vec2, vec3, vec4, mat3, mat4 } from 'wgpu-matrix';
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/// <reference types="dist" />
|
|
2
|
+
import { Mat4, Vector2, Vector3 } from './types.js';
|
|
3
|
+
import { Color } from './utils.js';
|
|
4
|
+
import { SimulationElement } from './graphics.js';
|
|
5
|
+
export declare class VertexCache {
|
|
6
|
+
private vertices;
|
|
7
|
+
private hasUpdated;
|
|
8
|
+
constructor();
|
|
9
|
+
setCache(vertices: number[]): void;
|
|
10
|
+
getCache(): number[];
|
|
11
|
+
updated(): void;
|
|
12
|
+
shouldUpdate(): boolean;
|
|
13
|
+
getVertexCount(): number;
|
|
14
|
+
}
|
|
15
|
+
export declare const buildProjectionMatrix: (aspectRatio: number, zNear?: number, zFar?: number) => any;
|
|
16
|
+
export declare const getTransformationMatrix: (pos: Vector3, rotation: Vector3, projectionMatrix: mat4) => Float32Array;
|
|
17
|
+
export declare const getOrthoMatrix: (screenSize: [number, number]) => Float32Array;
|
|
18
|
+
export declare const buildDepthTexture: (device: GPUDevice, width: number, height: number) => GPUTexture;
|
|
19
|
+
export declare const buildMultisampleTexture: (device: GPUDevice, ctx: GPUCanvasContext, width: number, height: number) => GPUTexture;
|
|
20
|
+
export declare const applyElementToScene: (scene: SimulationElement[], el: SimulationElement) => void;
|
|
21
|
+
declare class Logger {
|
|
22
|
+
constructor();
|
|
23
|
+
private fmt;
|
|
24
|
+
log(msg: string): void;
|
|
25
|
+
error(msg: string): Error;
|
|
26
|
+
warn(msg: string): void;
|
|
27
|
+
log_error(msg: string): void;
|
|
28
|
+
}
|
|
29
|
+
export declare const logger: Logger;
|
|
30
|
+
export declare function lossyTriangulate<T>(vertices: T[]): (readonly [T, T, T])[];
|
|
31
|
+
declare class BufferGenerator {
|
|
32
|
+
private instancing;
|
|
33
|
+
constructor();
|
|
34
|
+
setInstancing(state: boolean): void;
|
|
35
|
+
generate(x: number, y: number, z: number, color: Color, uv?: Vector2): number[];
|
|
36
|
+
}
|
|
37
|
+
export declare const bufferGenerator: BufferGenerator;
|
|
38
|
+
export declare function vector3ToPixelRatio(vec: Vector3): void;
|
|
39
|
+
export declare function vector2ToPixelRatio(vec: Vector2): void;
|
|
40
|
+
export declare function interpolateColors(colors: Color[], t: number): Color;
|
|
41
|
+
export declare function matrixFromRotation(rotation: Vector3): Mat4;
|
|
42
|
+
export declare function rotateMat4(mat: Mat4, rotation: Vector3): void;
|
|
43
|
+
export declare function createPipeline(device: GPUDevice, module: GPUShaderModule, bindGroupLayout: GPUBindGroupLayout, presentationFormat: GPUTextureFormat, entryPoint: string, topology: GPUPrimitiveTopology): GPURenderPipeline;
|
|
44
|
+
export declare function triangulateWireFrameOrder(len: number): number[];
|
|
45
|
+
export declare function getTotalVertices(scene: SimulationElement[]): number;
|
|
46
|
+
export {};
|
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
import { mat4, vec3 } from 'wgpu-matrix';
|
|
2
|
+
import { BUF_LEN, colorOffset, drawingInstancesOffset, uvOffset, vertexSize } from './constants.js';
|
|
3
|
+
import { color, vector2, vector3 } from './utils.js';
|
|
4
|
+
import { SimulationElement } from './graphics.js';
|
|
5
|
+
export class VertexCache {
|
|
6
|
+
vertices = [];
|
|
7
|
+
hasUpdated = true;
|
|
8
|
+
constructor() { }
|
|
9
|
+
setCache(vertices) {
|
|
10
|
+
this.vertices = vertices;
|
|
11
|
+
this.hasUpdated = false;
|
|
12
|
+
}
|
|
13
|
+
getCache() {
|
|
14
|
+
return this.vertices;
|
|
15
|
+
}
|
|
16
|
+
updated() {
|
|
17
|
+
this.hasUpdated = true;
|
|
18
|
+
}
|
|
19
|
+
shouldUpdate() {
|
|
20
|
+
return this.hasUpdated;
|
|
21
|
+
}
|
|
22
|
+
getVertexCount() {
|
|
23
|
+
return this.vertices.length / BUF_LEN;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
export const buildProjectionMatrix = (aspectRatio, zNear = 1, zFar = 500) => {
|
|
27
|
+
const fov = (2 * Math.PI) / 5;
|
|
28
|
+
return mat4.perspective(fov, aspectRatio, zNear, zFar);
|
|
29
|
+
};
|
|
30
|
+
export const getTransformationMatrix = (pos, rotation, projectionMatrix) => {
|
|
31
|
+
const modelViewProjectionMatrix = mat4.create();
|
|
32
|
+
const viewMatrix = mat4.identity();
|
|
33
|
+
const camPos = vector3();
|
|
34
|
+
vec3.clone(pos, camPos);
|
|
35
|
+
vec3.scale(camPos, -1, camPos);
|
|
36
|
+
mat4.rotateZ(viewMatrix, rotation[2], viewMatrix);
|
|
37
|
+
mat4.rotateY(viewMatrix, rotation[1], viewMatrix);
|
|
38
|
+
mat4.rotateX(viewMatrix, rotation[0], viewMatrix);
|
|
39
|
+
mat4.translate(viewMatrix, camPos, viewMatrix);
|
|
40
|
+
mat4.multiply(projectionMatrix, viewMatrix, modelViewProjectionMatrix);
|
|
41
|
+
return modelViewProjectionMatrix;
|
|
42
|
+
};
|
|
43
|
+
export const getOrthoMatrix = (screenSize) => {
|
|
44
|
+
return mat4.ortho(0, screenSize[0], 0, screenSize[1], 0, 100);
|
|
45
|
+
};
|
|
46
|
+
export const buildDepthTexture = (device, width, height) => {
|
|
47
|
+
return device.createTexture({
|
|
48
|
+
size: [width, height],
|
|
49
|
+
format: 'depth24plus',
|
|
50
|
+
usage: GPUTextureUsage.RENDER_ATTACHMENT,
|
|
51
|
+
sampleCount: 4
|
|
52
|
+
});
|
|
53
|
+
};
|
|
54
|
+
export const buildMultisampleTexture = (device, ctx, width, height) => {
|
|
55
|
+
return device.createTexture({
|
|
56
|
+
size: [width, height],
|
|
57
|
+
format: ctx.getCurrentTexture().format,
|
|
58
|
+
usage: GPUTextureUsage.RENDER_ATTACHMENT,
|
|
59
|
+
sampleCount: 4
|
|
60
|
+
});
|
|
61
|
+
};
|
|
62
|
+
export const applyElementToScene = (scene, el) => {
|
|
63
|
+
if (el instanceof SimulationElement) {
|
|
64
|
+
scene.unshift(el);
|
|
65
|
+
}
|
|
66
|
+
else {
|
|
67
|
+
throw logger.error('Cannot add invalid SimulationElement');
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
class Logger {
|
|
71
|
+
constructor() { }
|
|
72
|
+
fmt(msg) {
|
|
73
|
+
return `SimJS: ${msg}`;
|
|
74
|
+
}
|
|
75
|
+
log(msg) {
|
|
76
|
+
console.log(this.fmt(msg));
|
|
77
|
+
}
|
|
78
|
+
error(msg) {
|
|
79
|
+
return new Error(this.fmt(msg));
|
|
80
|
+
}
|
|
81
|
+
warn(msg) {
|
|
82
|
+
console.warn(this.fmt(msg));
|
|
83
|
+
}
|
|
84
|
+
log_error(msg) {
|
|
85
|
+
console.error(this.fmt(msg));
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
export const logger = new Logger();
|
|
89
|
+
// optomized for speed, depending on orientation of vertices as input, shape may not be preserved
|
|
90
|
+
export function lossyTriangulate(vertices) {
|
|
91
|
+
const res = [];
|
|
92
|
+
let facingRight = true;
|
|
93
|
+
let rightOffset = 0;
|
|
94
|
+
let leftOffset = 0;
|
|
95
|
+
while (rightOffset < vertices.length - leftOffset - 2) {
|
|
96
|
+
if (facingRight) {
|
|
97
|
+
const triangle = [
|
|
98
|
+
vertices[rightOffset],
|
|
99
|
+
vertices[rightOffset + 1],
|
|
100
|
+
vertices[vertices.length - leftOffset - 1]
|
|
101
|
+
];
|
|
102
|
+
res.push(triangle);
|
|
103
|
+
rightOffset++;
|
|
104
|
+
}
|
|
105
|
+
else {
|
|
106
|
+
const triangle = [
|
|
107
|
+
vertices[rightOffset],
|
|
108
|
+
vertices[vertices.length - leftOffset - 1],
|
|
109
|
+
vertices[vertices.length - leftOffset - 2]
|
|
110
|
+
];
|
|
111
|
+
res.push(triangle);
|
|
112
|
+
leftOffset++;
|
|
113
|
+
}
|
|
114
|
+
facingRight = !facingRight;
|
|
115
|
+
}
|
|
116
|
+
return res;
|
|
117
|
+
}
|
|
118
|
+
class BufferGenerator {
|
|
119
|
+
instancing = false;
|
|
120
|
+
constructor() { }
|
|
121
|
+
setInstancing(state) {
|
|
122
|
+
this.instancing = state;
|
|
123
|
+
}
|
|
124
|
+
generate(x, y, z, color, uv = vector2()) {
|
|
125
|
+
return [x, y, z, 1, ...color.toBuffer(), ...uv, this.instancing ? 1 : 0];
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
export const bufferGenerator = new BufferGenerator();
|
|
129
|
+
export function vector3ToPixelRatio(vec) {
|
|
130
|
+
vec[0] *= devicePixelRatio;
|
|
131
|
+
vec[1] *= devicePixelRatio;
|
|
132
|
+
vec[2] *= devicePixelRatio;
|
|
133
|
+
}
|
|
134
|
+
export function vector2ToPixelRatio(vec) {
|
|
135
|
+
vec[0] *= devicePixelRatio;
|
|
136
|
+
vec[1] *= devicePixelRatio;
|
|
137
|
+
}
|
|
138
|
+
export function interpolateColors(colors, t) {
|
|
139
|
+
t = Math.min(1, Math.max(0, t));
|
|
140
|
+
if (colors.length === 0)
|
|
141
|
+
return color();
|
|
142
|
+
if (colors.length === 1)
|
|
143
|
+
return colors[0];
|
|
144
|
+
const colorInterval = 1 / colors.length;
|
|
145
|
+
let index = Math.floor(t / colorInterval);
|
|
146
|
+
if (index >= colors.length)
|
|
147
|
+
index = colors.length - 1;
|
|
148
|
+
const from = index === colors.length - 1 ? colors[index - 1] : colors[index];
|
|
149
|
+
const to = index === colors.length - 1 ? colors[index] : colors[index + 1];
|
|
150
|
+
const diff = to.diff(from);
|
|
151
|
+
const scale = t / (colorInterval * colors.length);
|
|
152
|
+
diff.r *= scale;
|
|
153
|
+
diff.g *= scale;
|
|
154
|
+
diff.b *= scale;
|
|
155
|
+
diff.a *= scale;
|
|
156
|
+
const res = from.clone();
|
|
157
|
+
res.r += diff.r;
|
|
158
|
+
res.g += diff.g;
|
|
159
|
+
res.b += diff.b;
|
|
160
|
+
res.a += diff.a;
|
|
161
|
+
return res;
|
|
162
|
+
}
|
|
163
|
+
export function matrixFromRotation(rotation) {
|
|
164
|
+
let rotMatrix = mat4.identity();
|
|
165
|
+
mat4.rotateZ(rotMatrix, rotation[2], rotMatrix);
|
|
166
|
+
mat4.rotateY(rotMatrix, rotation[1], rotMatrix);
|
|
167
|
+
mat4.rotateX(rotMatrix, rotation[0], rotMatrix);
|
|
168
|
+
return rotMatrix;
|
|
169
|
+
}
|
|
170
|
+
export function rotateMat4(mat, rotation) {
|
|
171
|
+
mat4.rotateZ(mat, rotation[2], mat);
|
|
172
|
+
mat4.rotateY(mat, rotation[1], mat);
|
|
173
|
+
mat4.rotateX(mat, rotation[0], mat);
|
|
174
|
+
}
|
|
175
|
+
export function createPipeline(device, module, bindGroupLayout, presentationFormat, entryPoint, topology) {
|
|
176
|
+
return device.createRenderPipeline({
|
|
177
|
+
layout: device.createPipelineLayout({
|
|
178
|
+
bindGroupLayouts: [bindGroupLayout]
|
|
179
|
+
}),
|
|
180
|
+
vertex: {
|
|
181
|
+
module,
|
|
182
|
+
entryPoint,
|
|
183
|
+
buffers: [
|
|
184
|
+
{
|
|
185
|
+
arrayStride: vertexSize,
|
|
186
|
+
attributes: [
|
|
187
|
+
{
|
|
188
|
+
// position
|
|
189
|
+
shaderLocation: 0,
|
|
190
|
+
offset: 0,
|
|
191
|
+
format: 'float32x4'
|
|
192
|
+
},
|
|
193
|
+
{
|
|
194
|
+
// color
|
|
195
|
+
shaderLocation: 1,
|
|
196
|
+
offset: colorOffset,
|
|
197
|
+
format: 'float32x4'
|
|
198
|
+
},
|
|
199
|
+
{
|
|
200
|
+
// size
|
|
201
|
+
shaderLocation: 2,
|
|
202
|
+
offset: uvOffset,
|
|
203
|
+
format: 'float32x2'
|
|
204
|
+
},
|
|
205
|
+
{
|
|
206
|
+
// drawing instances
|
|
207
|
+
shaderLocation: 3,
|
|
208
|
+
offset: drawingInstancesOffset,
|
|
209
|
+
format: 'float32'
|
|
210
|
+
}
|
|
211
|
+
]
|
|
212
|
+
}
|
|
213
|
+
]
|
|
214
|
+
},
|
|
215
|
+
fragment: {
|
|
216
|
+
module,
|
|
217
|
+
entryPoint: 'fragment_main',
|
|
218
|
+
targets: [
|
|
219
|
+
{
|
|
220
|
+
format: presentationFormat
|
|
221
|
+
}
|
|
222
|
+
]
|
|
223
|
+
},
|
|
224
|
+
primitive: {
|
|
225
|
+
topology
|
|
226
|
+
},
|
|
227
|
+
multisample: {
|
|
228
|
+
count: 4
|
|
229
|
+
},
|
|
230
|
+
depthStencil: {
|
|
231
|
+
depthWriteEnabled: true,
|
|
232
|
+
depthCompare: 'less',
|
|
233
|
+
format: 'depth24plus'
|
|
234
|
+
}
|
|
235
|
+
});
|
|
236
|
+
}
|
|
237
|
+
export function triangulateWireFrameOrder(len) {
|
|
238
|
+
const order = Array(len)
|
|
239
|
+
.fill(0)
|
|
240
|
+
.map((_, index) => index);
|
|
241
|
+
let front = 0;
|
|
242
|
+
let back = len - 1;
|
|
243
|
+
while (front < back) {
|
|
244
|
+
order.push(front, back);
|
|
245
|
+
front++;
|
|
246
|
+
back--;
|
|
247
|
+
}
|
|
248
|
+
return order;
|
|
249
|
+
}
|
|
250
|
+
export function getTotalVertices(scene) {
|
|
251
|
+
let total = 0;
|
|
252
|
+
for (let i = 0; i < scene.length; i++) {
|
|
253
|
+
if (scene[i].isCollection)
|
|
254
|
+
continue;
|
|
255
|
+
total += scene[i].getVertexCount();
|
|
256
|
+
}
|
|
257
|
+
return total;
|
|
258
|
+
}
|
package/dist/simulation.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { vec3 } from 'wgpu-matrix';
|
|
2
2
|
import { SimulationElement3d } from './graphics.js';
|
|
3
3
|
import { BUF_LEN } from './constants.js';
|
|
4
|
-
import { Color,
|
|
4
|
+
import { Color, transitionValues, vector2, vector3 } from './utils.js';
|
|
5
5
|
import { BlankGeometry } from './geometry.js';
|
|
6
|
+
import { applyElementToScene, buildDepthTexture, buildMultisampleTexture, buildProjectionMatrix, createPipeline, getOrthoMatrix, getTotalVertices, getTransformationMatrix, logger } from './internalUtils.js';
|
|
6
7
|
const shader = `
|
|
7
8
|
struct Uniforms {
|
|
8
9
|
modelViewProjectionMatrix : mat4x4<f32>,
|
package/dist/types.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/// <reference types="dist" />
|
|
2
2
|
import { CubicBezierCurve2d, SplinePoint2d } from './graphics.js';
|
|
3
3
|
import { Color, Vertex } from './utils.js';
|
|
4
|
+
export type Shift<T extends any[]> = ((...args: T) => any) extends (arg1: any, ...rest: infer R) => any ? R : never;
|
|
4
5
|
export type FloatArray = Float32Array | Float64Array;
|
|
5
6
|
export type Vector4 = FloatArray & [number, number, number, number];
|
|
6
7
|
export type Vector3 = FloatArray & [number, number, number];
|
|
@@ -35,12 +36,13 @@ export type SquareGeometryParams = {
|
|
|
35
36
|
width: number;
|
|
36
37
|
height: number;
|
|
37
38
|
colorMap: VertexColorMap;
|
|
39
|
+
centerOffset: Vector2;
|
|
38
40
|
};
|
|
39
41
|
export type CircleGeometryParams = {
|
|
40
42
|
radius: number;
|
|
41
43
|
detail: number;
|
|
42
44
|
};
|
|
43
|
-
export type
|
|
45
|
+
export type Spline2dGeometryParams = {
|
|
44
46
|
points: SplinePoint2d[];
|
|
45
47
|
curves: CubicBezierCurve2d[];
|
|
46
48
|
distance: number;
|
package/dist/utils.d.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
import {
|
|
3
|
-
import { FloatArray, Mat4, Vector2, Vector3, Vector4 } from './types.js';
|
|
1
|
+
import { SplinePoint2d } from './graphics.js';
|
|
2
|
+
import { FloatArray, Mat4, Shift, Vector2, Vector3, Vector4 } from './types.js';
|
|
4
3
|
export declare class Color {
|
|
5
4
|
r: number;
|
|
6
5
|
g: number;
|
|
@@ -18,16 +17,6 @@ export declare class Color {
|
|
|
18
17
|
};
|
|
19
18
|
diff(color: Color): Color;
|
|
20
19
|
}
|
|
21
|
-
export declare class VertexCache {
|
|
22
|
-
private vertices;
|
|
23
|
-
private hasUpdated;
|
|
24
|
-
constructor();
|
|
25
|
-
setCache(vertices: number[]): void;
|
|
26
|
-
getCache(): number[];
|
|
27
|
-
updated(): void;
|
|
28
|
-
shouldUpdate(): boolean;
|
|
29
|
-
getVertexCount(): number;
|
|
30
|
-
}
|
|
31
20
|
export declare class Vertex {
|
|
32
21
|
private pos;
|
|
33
22
|
private color;
|
|
@@ -47,22 +36,6 @@ export declare class Vertex {
|
|
|
47
36
|
clone(): Vertex;
|
|
48
37
|
toBuffer(defaultColor: Color): number[];
|
|
49
38
|
}
|
|
50
|
-
export declare const buildProjectionMatrix: (aspectRatio: number, zNear?: number, zFar?: number) => any;
|
|
51
|
-
export declare const getTransformationMatrix: (pos: Vector3, rotation: Vector3, projectionMatrix: mat4) => Float32Array;
|
|
52
|
-
export declare const getOrthoMatrix: (screenSize: [number, number]) => Float32Array;
|
|
53
|
-
export declare const buildDepthTexture: (device: GPUDevice, width: number, height: number) => GPUTexture;
|
|
54
|
-
export declare const buildMultisampleTexture: (device: GPUDevice, ctx: GPUCanvasContext, width: number, height: number) => GPUTexture;
|
|
55
|
-
export declare const applyElementToScene: (scene: SimulationElement[], el: SimulationElement) => void;
|
|
56
|
-
declare class Logger {
|
|
57
|
-
constructor();
|
|
58
|
-
private fmt;
|
|
59
|
-
log(msg: string): void;
|
|
60
|
-
error(msg: string): Error;
|
|
61
|
-
warn(msg: string): void;
|
|
62
|
-
log_error(msg: string): void;
|
|
63
|
-
}
|
|
64
|
-
export declare const logger: Logger;
|
|
65
|
-
export declare function lossyTriangulate<T>(vertices: T[]): (readonly [T, T, T])[];
|
|
66
39
|
/**
|
|
67
40
|
* @param callback1 - called every frame until the animation is finished
|
|
68
41
|
* @param callback2 - called after animation is finished (called immediately when t = 0)
|
|
@@ -70,21 +43,13 @@ export declare function lossyTriangulate<T>(vertices: T[]): (readonly [T, T, T])
|
|
|
70
43
|
* @returns {Promise<void>}
|
|
71
44
|
*/
|
|
72
45
|
export declare function transitionValues(callback1: (deltaT: number, t: number) => void, callback2: () => void, transitionLength: number, func?: (n: number) => number): Promise<void>;
|
|
46
|
+
export declare function frameLoop<T extends (...args: any[]) => any>(cb: T): (...params: Shift<Parameters<T>>) => void;
|
|
73
47
|
export declare function lerp(a: number, b: number, t: number): number;
|
|
74
48
|
export declare function smoothStep(t: number): number;
|
|
75
49
|
export declare function linearStep(t: number): number;
|
|
76
50
|
export declare function easeInOutExpo(t: number): number;
|
|
77
51
|
export declare function easeInOutQuart(t: number): number;
|
|
78
52
|
export declare function easeInOutQuad(t: number): number;
|
|
79
|
-
declare class BufferGenerator {
|
|
80
|
-
private instancing;
|
|
81
|
-
constructor();
|
|
82
|
-
setInstancing(state: boolean): void;
|
|
83
|
-
generate(x: number, y: number, z: number, color: Color, uv?: Vector2): number[];
|
|
84
|
-
}
|
|
85
|
-
export declare const bufferGenerator: BufferGenerator;
|
|
86
|
-
export declare function vector3ToPixelRatio(vec: Vector3): void;
|
|
87
|
-
export declare function vector2ToPixelRatio(vec: Vector2): void;
|
|
88
53
|
export declare function cloneBuf<T extends FloatArray>(buf: T): T;
|
|
89
54
|
export declare function vector4(x?: number, y?: number, z?: number, w?: number): Vector4;
|
|
90
55
|
export declare function vector3(x?: number, y?: number, z?: number): Vector3;
|
|
@@ -100,14 +65,9 @@ export declare function color(r?: number, g?: number, b?: number, a?: number): C
|
|
|
100
65
|
export declare function colorf(val: number, a?: number): Color;
|
|
101
66
|
export declare function splinePoint2d(end: Vertex, control1: Vector2, control2: Vector2, detail?: number): SplinePoint2d;
|
|
102
67
|
export declare function continuousSplinePoint2d(end: Vertex, control: Vector2, detail?: number): SplinePoint2d;
|
|
103
|
-
export declare function interpolateColors(colors: Color[], t: number): Color;
|
|
104
68
|
/**
|
|
105
69
|
* @param t - seconds
|
|
106
70
|
*/
|
|
107
71
|
export declare function waitFor(t: number): Promise<unknown>;
|
|
108
|
-
export declare function
|
|
109
|
-
export declare function
|
|
110
|
-
export declare function createPipeline(device: GPUDevice, module: GPUShaderModule, bindGroupLayout: GPUBindGroupLayout, presentationFormat: GPUTextureFormat, entryPoint: string, topology: GPUPrimitiveTopology): GPURenderPipeline;
|
|
111
|
-
export declare function triangulateWireFrameOrder(len: number): number[];
|
|
112
|
-
export declare function getTotalVertices(scene: SimulationElement[]): number;
|
|
113
|
-
export {};
|
|
72
|
+
export declare function distance2d(vector1: Vector2, vector2: Vector2): number;
|
|
73
|
+
export declare function distance3d(vector1: Vector3, vector2: Vector3): number;
|
package/dist/utils.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { mat4, vec2, vec3, vec4 } from 'wgpu-matrix';
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
2
|
+
import { SplinePoint2d } from './graphics.js';
|
|
3
|
+
import { bufferGenerator } from './internalUtils.js';
|
|
4
4
|
export class Color {
|
|
5
5
|
r; // 0 - 255
|
|
6
6
|
g; // 0 - 255
|
|
@@ -33,27 +33,6 @@ export class Color {
|
|
|
33
33
|
return new Color(this.r - color.r, this.g - color.g, this.b - color.b, this.a - color.a);
|
|
34
34
|
}
|
|
35
35
|
}
|
|
36
|
-
export class VertexCache {
|
|
37
|
-
vertices = [];
|
|
38
|
-
hasUpdated = true;
|
|
39
|
-
constructor() { }
|
|
40
|
-
setCache(vertices) {
|
|
41
|
-
this.vertices = vertices;
|
|
42
|
-
this.hasUpdated = false;
|
|
43
|
-
}
|
|
44
|
-
getCache() {
|
|
45
|
-
return this.vertices;
|
|
46
|
-
}
|
|
47
|
-
updated() {
|
|
48
|
-
this.hasUpdated = true;
|
|
49
|
-
}
|
|
50
|
-
shouldUpdate() {
|
|
51
|
-
return this.hasUpdated;
|
|
52
|
-
}
|
|
53
|
-
getVertexCount() {
|
|
54
|
-
return this.vertices.length / BUF_LEN;
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
36
|
export class Vertex {
|
|
58
37
|
pos;
|
|
59
38
|
color;
|
|
@@ -105,98 +84,6 @@ export class Vertex {
|
|
|
105
84
|
return bufferGenerator.generate(this.pos[0], this.pos[1], 0, this.color || defaultColor, this.uv);
|
|
106
85
|
}
|
|
107
86
|
}
|
|
108
|
-
export const buildProjectionMatrix = (aspectRatio, zNear = 1, zFar = 500) => {
|
|
109
|
-
const fov = (2 * Math.PI) / 5;
|
|
110
|
-
return mat4.perspective(fov, aspectRatio, zNear, zFar);
|
|
111
|
-
};
|
|
112
|
-
export const getTransformationMatrix = (pos, rotation, projectionMatrix) => {
|
|
113
|
-
const modelViewProjectionMatrix = mat4.create();
|
|
114
|
-
const viewMatrix = mat4.identity();
|
|
115
|
-
const camPos = vector3();
|
|
116
|
-
vec3.clone(pos, camPos);
|
|
117
|
-
vec3.scale(camPos, -1, camPos);
|
|
118
|
-
mat4.rotateZ(viewMatrix, rotation[2], viewMatrix);
|
|
119
|
-
mat4.rotateY(viewMatrix, rotation[1], viewMatrix);
|
|
120
|
-
mat4.rotateX(viewMatrix, rotation[0], viewMatrix);
|
|
121
|
-
mat4.translate(viewMatrix, camPos, viewMatrix);
|
|
122
|
-
mat4.multiply(projectionMatrix, viewMatrix, modelViewProjectionMatrix);
|
|
123
|
-
return modelViewProjectionMatrix;
|
|
124
|
-
};
|
|
125
|
-
export const getOrthoMatrix = (screenSize) => {
|
|
126
|
-
return mat4.ortho(0, screenSize[0], 0, screenSize[1], 0, 100);
|
|
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
|
-
};
|
|
136
|
-
export const buildMultisampleTexture = (device, ctx, width, height) => {
|
|
137
|
-
return device.createTexture({
|
|
138
|
-
size: [width, height],
|
|
139
|
-
format: ctx.getCurrentTexture().format,
|
|
140
|
-
usage: GPUTextureUsage.RENDER_ATTACHMENT,
|
|
141
|
-
sampleCount: 4
|
|
142
|
-
});
|
|
143
|
-
};
|
|
144
|
-
export const applyElementToScene = (scene, el) => {
|
|
145
|
-
if (el instanceof SimulationElement) {
|
|
146
|
-
scene.push(el);
|
|
147
|
-
}
|
|
148
|
-
else {
|
|
149
|
-
throw logger.error('Cannot add invalid SimulationElement');
|
|
150
|
-
}
|
|
151
|
-
};
|
|
152
|
-
class Logger {
|
|
153
|
-
constructor() { }
|
|
154
|
-
fmt(msg) {
|
|
155
|
-
return `SimJS: ${msg}`;
|
|
156
|
-
}
|
|
157
|
-
log(msg) {
|
|
158
|
-
console.log(this.fmt(msg));
|
|
159
|
-
}
|
|
160
|
-
error(msg) {
|
|
161
|
-
return new Error(this.fmt(msg));
|
|
162
|
-
}
|
|
163
|
-
warn(msg) {
|
|
164
|
-
console.warn(this.fmt(msg));
|
|
165
|
-
}
|
|
166
|
-
log_error(msg) {
|
|
167
|
-
console.error(this.fmt(msg));
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
export const logger = new Logger();
|
|
171
|
-
// optomized for speed, depending on orientation of vertices as input, shape may not be preserved
|
|
172
|
-
export function lossyTriangulate(vertices) {
|
|
173
|
-
const res = [];
|
|
174
|
-
let facingRight = true;
|
|
175
|
-
let rightOffset = 0;
|
|
176
|
-
let leftOffset = 0;
|
|
177
|
-
while (rightOffset < vertices.length - leftOffset - 2) {
|
|
178
|
-
if (facingRight) {
|
|
179
|
-
const triangle = [
|
|
180
|
-
vertices[rightOffset],
|
|
181
|
-
vertices[rightOffset + 1],
|
|
182
|
-
vertices[vertices.length - leftOffset - 1]
|
|
183
|
-
];
|
|
184
|
-
res.push(triangle);
|
|
185
|
-
rightOffset++;
|
|
186
|
-
}
|
|
187
|
-
else {
|
|
188
|
-
const triangle = [
|
|
189
|
-
vertices[rightOffset],
|
|
190
|
-
vertices[vertices.length - leftOffset - 1],
|
|
191
|
-
vertices[vertices.length - leftOffset - 2]
|
|
192
|
-
];
|
|
193
|
-
res.push(triangle);
|
|
194
|
-
leftOffset++;
|
|
195
|
-
}
|
|
196
|
-
facingRight = !facingRight;
|
|
197
|
-
}
|
|
198
|
-
return res;
|
|
199
|
-
}
|
|
200
87
|
/**
|
|
201
88
|
* @param callback1 - called every frame until the animation is finished
|
|
202
89
|
* @param callback2 - called after animation is finished (called immediately when t = 0)
|
|
@@ -234,6 +121,27 @@ export function transitionValues(callback1, callback2, transitionLength, func) {
|
|
|
234
121
|
}
|
|
235
122
|
});
|
|
236
123
|
}
|
|
124
|
+
export function frameLoop(cb) {
|
|
125
|
+
let prevFrame = 0;
|
|
126
|
+
let prevTime = 0;
|
|
127
|
+
function start(dt, ...args) {
|
|
128
|
+
let res = cb(dt, ...args);
|
|
129
|
+
if (res === false) {
|
|
130
|
+
window.cancelAnimationFrame(prevFrame);
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
if (!Array.isArray(res))
|
|
134
|
+
res = args;
|
|
135
|
+
const now = Date.now();
|
|
136
|
+
const diff = now - prevTime;
|
|
137
|
+
prevTime = now;
|
|
138
|
+
prevFrame = window.requestAnimationFrame(() => start(diff, ...res));
|
|
139
|
+
}
|
|
140
|
+
return (...p) => {
|
|
141
|
+
prevTime = Date.now();
|
|
142
|
+
start(0, ...p);
|
|
143
|
+
};
|
|
144
|
+
}
|
|
237
145
|
export function lerp(a, b, t) {
|
|
238
146
|
return a + (b - a) * t;
|
|
239
147
|
}
|
|
@@ -260,26 +168,6 @@ export function easeInOutQuart(t) {
|
|
|
260
168
|
export function easeInOutQuad(t) {
|
|
261
169
|
return t < 0.5 ? 2 * t * t : 1 - Math.pow(-2 * t + 2, 2) / 2;
|
|
262
170
|
}
|
|
263
|
-
class BufferGenerator {
|
|
264
|
-
instancing = false;
|
|
265
|
-
constructor() { }
|
|
266
|
-
setInstancing(state) {
|
|
267
|
-
this.instancing = state;
|
|
268
|
-
}
|
|
269
|
-
generate(x, y, z, color, uv = vector2()) {
|
|
270
|
-
return [x, y, z, 1, ...color.toBuffer(), ...uv, this.instancing ? 1 : 0];
|
|
271
|
-
}
|
|
272
|
-
}
|
|
273
|
-
export const bufferGenerator = new BufferGenerator();
|
|
274
|
-
export function vector3ToPixelRatio(vec) {
|
|
275
|
-
vec[0] *= devicePixelRatio;
|
|
276
|
-
vec[1] *= devicePixelRatio;
|
|
277
|
-
vec[2] *= devicePixelRatio;
|
|
278
|
-
}
|
|
279
|
-
export function vector2ToPixelRatio(vec) {
|
|
280
|
-
vec[0] *= devicePixelRatio;
|
|
281
|
-
vec[1] *= devicePixelRatio;
|
|
282
|
-
}
|
|
283
171
|
export function cloneBuf(buf) {
|
|
284
172
|
return new Float32Array(buf);
|
|
285
173
|
}
|
|
@@ -334,31 +222,6 @@ export function continuousSplinePoint2d(end, control, detail) {
|
|
|
334
222
|
vec2.add(end.getPos(), control, control);
|
|
335
223
|
return new SplinePoint2d(null, end, null, control, rawControls, detail);
|
|
336
224
|
}
|
|
337
|
-
export function interpolateColors(colors, t) {
|
|
338
|
-
t = Math.min(1, Math.max(0, t));
|
|
339
|
-
if (colors.length === 0)
|
|
340
|
-
return color();
|
|
341
|
-
if (colors.length === 1)
|
|
342
|
-
return colors[0];
|
|
343
|
-
const colorInterval = 1 / colors.length;
|
|
344
|
-
let index = Math.floor(t / colorInterval);
|
|
345
|
-
if (index >= colors.length)
|
|
346
|
-
index = colors.length - 1;
|
|
347
|
-
const from = index === colors.length - 1 ? colors[index - 1] : colors[index];
|
|
348
|
-
const to = index === colors.length - 1 ? colors[index] : colors[index + 1];
|
|
349
|
-
const diff = to.diff(from);
|
|
350
|
-
const scale = t / (colorInterval * colors.length);
|
|
351
|
-
diff.r *= scale;
|
|
352
|
-
diff.g *= scale;
|
|
353
|
-
diff.b *= scale;
|
|
354
|
-
diff.a *= scale;
|
|
355
|
-
const res = from.clone();
|
|
356
|
-
res.r += diff.r;
|
|
357
|
-
res.g += diff.g;
|
|
358
|
-
res.b += diff.b;
|
|
359
|
-
res.a += diff.a;
|
|
360
|
-
return res;
|
|
361
|
-
}
|
|
362
225
|
/**
|
|
363
226
|
* @param t - seconds
|
|
364
227
|
*/
|
|
@@ -367,99 +230,9 @@ export function waitFor(t) {
|
|
|
367
230
|
setTimeout(resolve, t * 1000);
|
|
368
231
|
});
|
|
369
232
|
}
|
|
370
|
-
export function
|
|
371
|
-
|
|
372
|
-
mat4.rotateZ(rotMatrix, rotation[2], rotMatrix);
|
|
373
|
-
mat4.rotateY(rotMatrix, rotation[1], rotMatrix);
|
|
374
|
-
mat4.rotateX(rotMatrix, rotation[0], rotMatrix);
|
|
375
|
-
return rotMatrix;
|
|
233
|
+
export function distance2d(vector1, vector2) {
|
|
234
|
+
return vec2.distance(vector1, vector2);
|
|
376
235
|
}
|
|
377
|
-
export function
|
|
378
|
-
|
|
379
|
-
mat4.rotateY(mat, rotation[1], mat);
|
|
380
|
-
mat4.rotateX(mat, rotation[0], mat);
|
|
381
|
-
}
|
|
382
|
-
export function createPipeline(device, module, bindGroupLayout, presentationFormat, entryPoint, topology) {
|
|
383
|
-
return device.createRenderPipeline({
|
|
384
|
-
layout: device.createPipelineLayout({
|
|
385
|
-
bindGroupLayouts: [bindGroupLayout]
|
|
386
|
-
}),
|
|
387
|
-
vertex: {
|
|
388
|
-
module,
|
|
389
|
-
entryPoint,
|
|
390
|
-
buffers: [
|
|
391
|
-
{
|
|
392
|
-
arrayStride: vertexSize,
|
|
393
|
-
attributes: [
|
|
394
|
-
{
|
|
395
|
-
// position
|
|
396
|
-
shaderLocation: 0,
|
|
397
|
-
offset: 0,
|
|
398
|
-
format: 'float32x4'
|
|
399
|
-
},
|
|
400
|
-
{
|
|
401
|
-
// color
|
|
402
|
-
shaderLocation: 1,
|
|
403
|
-
offset: colorOffset,
|
|
404
|
-
format: 'float32x4'
|
|
405
|
-
},
|
|
406
|
-
{
|
|
407
|
-
// size
|
|
408
|
-
shaderLocation: 2,
|
|
409
|
-
offset: uvOffset,
|
|
410
|
-
format: 'float32x2'
|
|
411
|
-
},
|
|
412
|
-
{
|
|
413
|
-
// drawing instances
|
|
414
|
-
shaderLocation: 3,
|
|
415
|
-
offset: drawingInstancesOffset,
|
|
416
|
-
format: 'float32'
|
|
417
|
-
}
|
|
418
|
-
]
|
|
419
|
-
}
|
|
420
|
-
]
|
|
421
|
-
},
|
|
422
|
-
fragment: {
|
|
423
|
-
module,
|
|
424
|
-
entryPoint: 'fragment_main',
|
|
425
|
-
targets: [
|
|
426
|
-
{
|
|
427
|
-
format: presentationFormat
|
|
428
|
-
}
|
|
429
|
-
]
|
|
430
|
-
},
|
|
431
|
-
primitive: {
|
|
432
|
-
topology
|
|
433
|
-
},
|
|
434
|
-
multisample: {
|
|
435
|
-
count: 4
|
|
436
|
-
},
|
|
437
|
-
depthStencil: {
|
|
438
|
-
depthWriteEnabled: true,
|
|
439
|
-
depthCompare: 'less',
|
|
440
|
-
format: 'depth24plus'
|
|
441
|
-
}
|
|
442
|
-
});
|
|
443
|
-
}
|
|
444
|
-
export function triangulateWireFrameOrder(len) {
|
|
445
|
-
const order = Array(len)
|
|
446
|
-
.fill(0)
|
|
447
|
-
.map((_, index) => index);
|
|
448
|
-
let front = 0;
|
|
449
|
-
let back = len - 1;
|
|
450
|
-
while (front < back) {
|
|
451
|
-
order.push(front, back);
|
|
452
|
-
front++;
|
|
453
|
-
back--;
|
|
454
|
-
}
|
|
455
|
-
return order;
|
|
456
|
-
}
|
|
457
|
-
export function getTotalVertices(scene) {
|
|
458
|
-
let total = 0;
|
|
459
|
-
for (let i = 0; i < scene.length; i++) {
|
|
460
|
-
if (scene[i].isCollection)
|
|
461
|
-
continue;
|
|
462
|
-
total += scene[i].getVertexCount();
|
|
463
|
-
}
|
|
464
|
-
return total;
|
|
236
|
+
export function distance3d(vector1, vector2) {
|
|
237
|
+
return vec3.distance(vector1, vector2);
|
|
465
238
|
}
|
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.
|
|
8
|
+
"version": "0.3.1",
|
|
9
9
|
"exports": {
|
|
10
10
|
".": {
|
|
11
11
|
"import": "./dist/index.js",
|
|
@@ -24,6 +24,6 @@
|
|
|
24
24
|
},
|
|
25
25
|
"dependencies": {
|
|
26
26
|
"@webgpu/types": "^0.1.34",
|
|
27
|
-
"wgpu-matrix": "^2.
|
|
27
|
+
"wgpu-matrix": "^2.8.0"
|
|
28
28
|
}
|
|
29
29
|
}
|