simulationjsv2 0.2.8 → 0.3.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/TODO.md +4 -0
- package/dist/constants.d.ts +4 -2
- package/dist/constants.js +4 -2
- package/dist/geometry.d.ts +10 -6
- package/dist/geometry.js +40 -22
- package/dist/graphics.d.ts +30 -8
- package/dist/graphics.js +107 -18
- package/dist/index.d.ts +2 -1
- package/dist/index.js +2 -1
- package/dist/simulation.d.ts +3 -1
- package/dist/simulation.js +103 -35
- package/dist/types.d.ts +12 -5
- package/dist/utils.d.ts +11 -4
- package/dist/utils.js +33 -8
- package/package.json +1 -1
package/TODO.md
ADDED
package/dist/constants.d.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
export declare const
|
|
2
|
-
export declare const
|
|
1
|
+
export declare const vertexSize = 44;
|
|
2
|
+
export declare const positionOffset = 0;
|
|
3
3
|
export declare const colorOffset = 16;
|
|
4
4
|
export declare const uvOffset = 32;
|
|
5
|
+
export declare const drawingInstancesOffset = 40;
|
|
6
|
+
export declare const BUF_LEN: number;
|
package/dist/constants.js
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
export const
|
|
2
|
-
export const
|
|
1
|
+
export const vertexSize = 44; // 4 * 10
|
|
2
|
+
export const positionOffset = 0;
|
|
3
3
|
export const colorOffset = 16; // 4 * 4
|
|
4
4
|
export const uvOffset = 32; // 4 * 8
|
|
5
|
+
export const drawingInstancesOffset = 40;
|
|
6
|
+
export const BUF_LEN = vertexSize / 4;
|
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[];
|
|
@@ -24,7 +24,6 @@ export declare class PlaneGeometry extends Geometry {
|
|
|
24
24
|
protected triangleOrder: number[];
|
|
25
25
|
private rawVertices;
|
|
26
26
|
constructor(vertices: Vertex[]);
|
|
27
|
-
private updateWireframeOrder;
|
|
28
27
|
recompute(): void;
|
|
29
28
|
updateVertices(vertices: Vertex[]): void;
|
|
30
29
|
getTriangleBuffer(color: Color): number[];
|
|
@@ -44,7 +43,7 @@ export declare class SquareGeometry extends Geometry {
|
|
|
44
43
|
protected wireframeOrder: number[];
|
|
45
44
|
protected triangleOrder: number[];
|
|
46
45
|
protected params: SquareGeometryParams;
|
|
47
|
-
constructor(width: number, height: number);
|
|
46
|
+
constructor(width: number, height: number, centerOffset?: Vector2);
|
|
48
47
|
setVertexColorMap(colorMap: VertexColorMap): void;
|
|
49
48
|
setWidth(width: number): void;
|
|
50
49
|
setHeight(height: number): void;
|
|
@@ -68,13 +67,18 @@ export declare class CircleGeometry extends Geometry {
|
|
|
68
67
|
private updateTriangleOrder;
|
|
69
68
|
recompute(): void;
|
|
70
69
|
}
|
|
71
|
-
export declare class
|
|
70
|
+
export declare class Spline2dGeometry extends Geometry {
|
|
72
71
|
protected wireframeOrder: number[];
|
|
73
72
|
protected triangleOrder: number[];
|
|
74
|
-
protected params:
|
|
73
|
+
protected params: Spline2dGeometryParams;
|
|
75
74
|
constructor(points: SplinePoint2d[], color: Color, thickness: number, detail: number);
|
|
76
75
|
updateInterpolationStart(start: number): void;
|
|
77
76
|
updateInterpolationLimit(limit: number): void;
|
|
77
|
+
updateThickness(thickness: number): void;
|
|
78
|
+
private getVertexCount;
|
|
79
|
+
getWireframeVertexCount(): number;
|
|
80
|
+
getTriangleVertexCount(): number;
|
|
81
|
+
getCurves(): CubicBezierCurve2d[];
|
|
78
82
|
private computeCurves;
|
|
79
83
|
private updateWireframeOrder;
|
|
80
84
|
recompute(): void;
|
package/dist/geometry.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { mat4, vec2, vec3 } from 'wgpu-matrix';
|
|
2
|
-
import { cloneBuf, interpolateColors, lossyTriangulate, matrix4, triangulateWireFrameOrder, vector2, vector2FromVector3, vector3, vector3FromVector2, vertex,
|
|
2
|
+
import { cloneBuf, interpolateColors, lossyTriangulate, matrix4, triangulateWireFrameOrder, vector2, vector2FromVector3, vector3, vector3FromVector2, vertex, bufferGenerator } from './utils.js';
|
|
3
3
|
import { CubicBezierCurve2d } from './graphics.js';
|
|
4
|
+
import { BUF_LEN } from './constants.js';
|
|
4
5
|
export class Geometry {
|
|
5
6
|
vertices;
|
|
6
7
|
matrix;
|
|
@@ -27,7 +28,7 @@ export class Geometry {
|
|
|
27
28
|
.map((vertexIndex) => {
|
|
28
29
|
const pos = cloneBuf(this.vertices[vertexIndex]);
|
|
29
30
|
vec3.transformMat4(pos, this.matrix, pos);
|
|
30
|
-
return
|
|
31
|
+
return bufferGenerator.generate(pos[0], pos[1], pos[2], color);
|
|
31
32
|
})
|
|
32
33
|
.flat();
|
|
33
34
|
}
|
|
@@ -50,22 +51,22 @@ export class PlaneGeometry extends Geometry {
|
|
|
50
51
|
this.rawVertices = vertices;
|
|
51
52
|
this.updateVertices(vertices);
|
|
52
53
|
}
|
|
53
|
-
updateWireframeOrder() {
|
|
54
|
-
this.wireframeOrder = triangulateWireFrameOrder(this.vertices.length);
|
|
55
|
-
}
|
|
56
54
|
recompute() { }
|
|
57
55
|
updateVertices(vertices) {
|
|
58
56
|
this.rawVertices = vertices;
|
|
59
57
|
this.vertices = vertices.map((vertex) => vertex.getPos());
|
|
60
|
-
this.
|
|
58
|
+
this.wireframeOrder = triangulateWireFrameOrder(this.vertices.length);
|
|
59
|
+
this.triangleOrder = lossyTriangulate(Array(this.rawVertices.length)
|
|
60
|
+
.fill(0)
|
|
61
|
+
.map((_, index) => index)).flat();
|
|
61
62
|
}
|
|
62
63
|
getTriangleBuffer(color) {
|
|
63
|
-
return
|
|
64
|
-
.
|
|
65
|
-
|
|
64
|
+
return this.triangleOrder
|
|
65
|
+
.map((index) => {
|
|
66
|
+
const vertex = this.rawVertices[index];
|
|
66
67
|
const pos = cloneBuf(vertex.getPos());
|
|
67
68
|
vec3.transformMat4(pos, this.matrix, pos);
|
|
68
|
-
return
|
|
69
|
+
return bufferGenerator.generate(pos[0], pos[1], pos[2], vertex.getColor() || color);
|
|
69
70
|
})
|
|
70
71
|
.flat();
|
|
71
72
|
}
|
|
@@ -125,12 +126,13 @@ export class SquareGeometry extends Geometry {
|
|
|
125
126
|
wireframeOrder = [0, 1, 2, 3, 0, 2];
|
|
126
127
|
triangleOrder = [0, 1, 3, 2];
|
|
127
128
|
params;
|
|
128
|
-
constructor(width, height) {
|
|
129
|
+
constructor(width, height, centerOffset) {
|
|
129
130
|
super([], 'strip');
|
|
130
131
|
this.params = {
|
|
131
132
|
width,
|
|
132
133
|
height,
|
|
133
|
-
colorMap: {}
|
|
134
|
+
colorMap: {},
|
|
135
|
+
centerOffset: centerOffset || vector2(0, 0)
|
|
134
136
|
};
|
|
135
137
|
this.recompute();
|
|
136
138
|
}
|
|
@@ -144,11 +146,12 @@ export class SquareGeometry extends Geometry {
|
|
|
144
146
|
this.params.height = height;
|
|
145
147
|
}
|
|
146
148
|
recompute() {
|
|
149
|
+
const centerOffset = this.params.centerOffset;
|
|
147
150
|
this.vertices = [
|
|
148
|
-
vector3(-this.params.width
|
|
149
|
-
vector3(this.params.width
|
|
150
|
-
vector3(this.params.width
|
|
151
|
-
vector3(-this.params.width
|
|
151
|
+
vector3(-this.params.width * centerOffset[0], this.params.height * centerOffset[1]),
|
|
152
|
+
vector3(this.params.width * (1 - centerOffset[0]), this.params.height * centerOffset[1]),
|
|
153
|
+
vector3(this.params.width * (1 - centerOffset[0]), -this.params.height * (1 - centerOffset[1])),
|
|
154
|
+
vector3(-this.params.width * centerOffset[0], -this.params.height * (1 - centerOffset[1]))
|
|
152
155
|
];
|
|
153
156
|
}
|
|
154
157
|
getTriangleBuffer(color) {
|
|
@@ -156,7 +159,7 @@ export class SquareGeometry extends Geometry {
|
|
|
156
159
|
.map((vertexIndex) => {
|
|
157
160
|
const pos = cloneBuf(this.vertices[vertexIndex]);
|
|
158
161
|
vec3.transformMat4(pos, this.matrix, pos);
|
|
159
|
-
return
|
|
162
|
+
return bufferGenerator.generate(pos[0], pos[1], pos[2], this.params.colorMap[vertexIndex] || color);
|
|
160
163
|
})
|
|
161
164
|
.flat();
|
|
162
165
|
}
|
|
@@ -207,12 +210,12 @@ export class CircleGeometry extends Geometry {
|
|
|
207
210
|
this.updateWireframeOrder();
|
|
208
211
|
}
|
|
209
212
|
}
|
|
210
|
-
export class
|
|
213
|
+
export class Spline2dGeometry extends Geometry {
|
|
211
214
|
wireframeOrder;
|
|
212
215
|
triangleOrder;
|
|
213
216
|
params;
|
|
214
217
|
constructor(points, color, thickness, detail) {
|
|
215
|
-
super(
|
|
218
|
+
super();
|
|
216
219
|
this.wireframeOrder = [];
|
|
217
220
|
this.triangleOrder = [];
|
|
218
221
|
this.params = {
|
|
@@ -235,6 +238,21 @@ export class SplineGeometry extends Geometry {
|
|
|
235
238
|
updateInterpolationLimit(limit) {
|
|
236
239
|
this.params.interpolateLimit = Math.min(1, Math.max(0, limit));
|
|
237
240
|
}
|
|
241
|
+
updateThickness(thickness) {
|
|
242
|
+
this.params.thickness = thickness;
|
|
243
|
+
}
|
|
244
|
+
getVertexCount() {
|
|
245
|
+
return this.triangleOrder.length * BUF_LEN;
|
|
246
|
+
}
|
|
247
|
+
getWireframeVertexCount() {
|
|
248
|
+
return this.getVertexCount();
|
|
249
|
+
}
|
|
250
|
+
getTriangleVertexCount() {
|
|
251
|
+
return this.getVertexCount();
|
|
252
|
+
}
|
|
253
|
+
getCurves() {
|
|
254
|
+
return this.params.curves;
|
|
255
|
+
}
|
|
238
256
|
computeCurves() {
|
|
239
257
|
for (let i = 0; i < this.params.points.length; i++) {
|
|
240
258
|
let prevControl = null;
|
|
@@ -319,7 +337,7 @@ export class SplineGeometry extends Geometry {
|
|
|
319
337
|
.map((vertexIndex) => {
|
|
320
338
|
const vertex = cloneBuf(this.vertices[vertexIndex]);
|
|
321
339
|
vec3.transformMat4(vertex, this.matrix, vertex);
|
|
322
|
-
return
|
|
340
|
+
return bufferGenerator.generate(vertex[0], vertex[1], vertex[2], color);
|
|
323
341
|
})
|
|
324
342
|
.flat();
|
|
325
343
|
}
|
|
@@ -328,7 +346,7 @@ export class SplineGeometry extends Geometry {
|
|
|
328
346
|
.map((vertexIndex) => {
|
|
329
347
|
const vertex = cloneBuf(this.vertices[vertexIndex]);
|
|
330
348
|
vec3.transformMat4(vertex, this.matrix, vertex);
|
|
331
|
-
return
|
|
349
|
+
return bufferGenerator.generate(vertex[0], vertex[1], vertex[2], this.params.vertexColors[vertexIndex]);
|
|
332
350
|
})
|
|
333
351
|
.flat();
|
|
334
352
|
}
|
|
@@ -406,7 +424,7 @@ export class PolygonGeometry extends Geometry {
|
|
|
406
424
|
.map((vertexIndex) => {
|
|
407
425
|
const vertex = cloneBuf(this.vertices[vertexIndex]);
|
|
408
426
|
vec3.transformMat4(vertex, this.matrix, vertex);
|
|
409
|
-
return
|
|
427
|
+
return bufferGenerator.generate(vertex[0], vertex[1], 0, this.params.points[vertexIndex].getColor() || color);
|
|
410
428
|
})
|
|
411
429
|
.flat();
|
|
412
430
|
}
|
package/dist/graphics.d.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
+
/// <reference types="dist" />
|
|
1
2
|
import { Camera } from './simulation.js';
|
|
2
|
-
import type { Vector2, Vector3, LerpFunc, VertexColorMap, ElementRotation } from './types.js';
|
|
3
|
+
import type { Vector2, Vector3, LerpFunc, VertexColorMap, ElementRotation, Mat4 } from './types.js';
|
|
3
4
|
import { Vertex, VertexCache, Color } from './utils.js';
|
|
4
|
-
import { CircleGeometry, CubeGeometry, Geometry, Line2dGeometry, Line3dGeometry, PlaneGeometry, PolygonGeometry,
|
|
5
|
+
import { BlankGeometry, CircleGeometry, CubeGeometry, Geometry, Line2dGeometry, Line3dGeometry, PlaneGeometry, PolygonGeometry, Spline2dGeometry, SquareGeometry } from './geometry.js';
|
|
5
6
|
export declare abstract class SimulationElement<T extends Vector2 | Vector3 = Vector3> {
|
|
6
7
|
protected abstract pos: T;
|
|
7
8
|
protected abstract geometry: Geometry;
|
|
@@ -9,16 +10,17 @@ export declare abstract class SimulationElement<T extends Vector2 | Vector3 = Ve
|
|
|
9
10
|
protected wireframe: boolean;
|
|
10
11
|
protected vertexCache: VertexCache;
|
|
11
12
|
protected rotation: ElementRotation<T>;
|
|
12
|
-
|
|
13
|
+
isInstanced: boolean;
|
|
13
14
|
/**
|
|
14
15
|
* @param pos - Expected to be adjusted to devicePixelRatio before reaching constructor
|
|
15
16
|
*/
|
|
16
|
-
constructor(color: Color | undefined, rotation: ElementRotation<T
|
|
17
|
+
constructor(color: Color | undefined, rotation: ElementRotation<T>);
|
|
17
18
|
getGeometryType(): "list" | "strip";
|
|
18
19
|
setWireframe(wireframe: boolean): void;
|
|
19
20
|
isWireframe(): boolean;
|
|
20
21
|
getColor(): Color;
|
|
21
22
|
getPos(): T;
|
|
23
|
+
getRotation(): ElementRotation<T>;
|
|
22
24
|
fill(newColor: Color, t?: number, f?: LerpFunc): Promise<void>;
|
|
23
25
|
abstract move(amount: T, t?: number, f?: LerpFunc): Promise<void>;
|
|
24
26
|
abstract moveTo(pos: T, t?: number, f?: LerpFunc): Promise<void>;
|
|
@@ -31,7 +33,8 @@ export declare abstract class SimulationElement<T extends Vector2 | Vector3 = Ve
|
|
|
31
33
|
}
|
|
32
34
|
export declare abstract class SimulationElement3d extends SimulationElement {
|
|
33
35
|
protected pos: Vector3;
|
|
34
|
-
rotation: Vector3;
|
|
36
|
+
protected rotation: Vector3;
|
|
37
|
+
is3d: boolean;
|
|
35
38
|
constructor(pos: Vector3, rotation?: Vector3, color?: Color);
|
|
36
39
|
rotate(amount: Vector3, t?: number, f?: LerpFunc): Promise<void>;
|
|
37
40
|
rotateTo(rot: Vector3, t?: number, f?: LerpFunc): Promise<void>;
|
|
@@ -60,9 +63,10 @@ export declare class Square extends SimulationElement2d {
|
|
|
60
63
|
private height;
|
|
61
64
|
private vertexColors;
|
|
62
65
|
/**
|
|
66
|
+
* @param centerOffset{Vector2} - A vector2 of values from 0 to 1
|
|
63
67
|
* @param vertexColors{Record<number, Color>} - 0 is top left vertex, numbers increase clockwise
|
|
64
68
|
*/
|
|
65
|
-
constructor(pos: Vector2, width: number, height: number, color?: Color, rotation?: number, vertexColors?: VertexColorMap);
|
|
69
|
+
constructor(pos: Vector2, width: number, height: number, color?: Color, rotation?: number, centerOffset?: Vector2, vertexColors?: VertexColorMap);
|
|
66
70
|
private cloneColorMap;
|
|
67
71
|
setVertexColors(newColorMap: VertexColorMap, t?: number, f?: LerpFunc): Promise<void>;
|
|
68
72
|
scaleWidth(amount: number, t?: number, f?: LerpFunc): Promise<void>;
|
|
@@ -151,8 +155,7 @@ export declare class SplinePoint2d {
|
|
|
151
155
|
getVectorArray(prevEnd: Vector2 | null, prevControl: Vector2 | null): readonly [Vector2, Vector2, Vector2, Vector2];
|
|
152
156
|
}
|
|
153
157
|
export declare class Spline2d extends SimulationElement2d {
|
|
154
|
-
protected geometry:
|
|
155
|
-
private curves;
|
|
158
|
+
protected geometry: Spline2dGeometry;
|
|
156
159
|
private thickness;
|
|
157
160
|
private detail;
|
|
158
161
|
private interpolateStart;
|
|
@@ -160,7 +163,26 @@ export declare class Spline2d extends SimulationElement2d {
|
|
|
160
163
|
constructor(pos: Vertex, points: SplinePoint2d[], thickness?: number, detail?: number);
|
|
161
164
|
setInterpolateStart(start: number, t?: number, f?: LerpFunc): Promise<void>;
|
|
162
165
|
setInterpolateLimit(limit: number, t?: number, f?: LerpFunc): Promise<void>;
|
|
166
|
+
setThickness(thickness: number, t?: number, f?: LerpFunc): Promise<void>;
|
|
163
167
|
interpolateSlope(t: number): readonly [Vector2, Vector2];
|
|
164
168
|
interpolate(t: number): Vector2;
|
|
165
169
|
protected updateMatrix(camera: Camera): void;
|
|
166
170
|
}
|
|
171
|
+
export declare class Instance<T extends SimulationElement2d | SimulationElement3d> extends SimulationElement3d {
|
|
172
|
+
protected geometry: BlankGeometry;
|
|
173
|
+
private obj;
|
|
174
|
+
private instanceMatrix;
|
|
175
|
+
private matrixBuffer;
|
|
176
|
+
private device;
|
|
177
|
+
readonly isInstance = true;
|
|
178
|
+
constructor(obj: T, numInstances: number);
|
|
179
|
+
private setMatrixBuffer;
|
|
180
|
+
getInstances(): Mat4[];
|
|
181
|
+
getNumInstances(): number;
|
|
182
|
+
setDevice(device: GPUDevice): void;
|
|
183
|
+
getMatrixBuffer(): GPUBuffer | null;
|
|
184
|
+
getVertexCount(): number;
|
|
185
|
+
getGeometryType(): "list" | "strip";
|
|
186
|
+
protected updateMatrix(_: Camera): void;
|
|
187
|
+
getBuffer(camera: Camera): number[];
|
|
188
|
+
}
|
package/dist/graphics.js
CHANGED
|
@@ -1,21 +1,21 @@
|
|
|
1
1
|
import { vec3, mat4, vec2, vec4 } from 'wgpu-matrix';
|
|
2
|
-
import { Vertex, VertexCache, cloneBuf, color, colorFromVector4, vector3ToPixelRatio, vector2, vector3, vertex, Color, transitionValues, logger, vector2FromVector3, matrix4, rotateMat4, vector3FromVector2, vector2ToPixelRatio } from './utils.js';
|
|
3
|
-
import { CircleGeometry, CubeGeometry, Line2dGeometry, Line3dGeometry, PlaneGeometry, PolygonGeometry,
|
|
2
|
+
import { Vertex, VertexCache, cloneBuf, color, colorFromVector4, vector3ToPixelRatio, vector2, vector3, vertex, Color, transitionValues, logger, vector2FromVector3, matrix4, rotateMat4, vector3FromVector2, vector2ToPixelRatio, bufferGenerator } from './utils.js';
|
|
3
|
+
import { BlankGeometry, CircleGeometry, CubeGeometry, Line2dGeometry, Line3dGeometry, PlaneGeometry, PolygonGeometry, Spline2dGeometry, SquareGeometry } from './geometry.js';
|
|
4
4
|
export class SimulationElement {
|
|
5
5
|
color;
|
|
6
6
|
wireframe;
|
|
7
7
|
vertexCache;
|
|
8
8
|
rotation;
|
|
9
|
-
|
|
9
|
+
isInstanced;
|
|
10
10
|
/**
|
|
11
11
|
* @param pos - Expected to be adjusted to devicePixelRatio before reaching constructor
|
|
12
12
|
*/
|
|
13
|
-
constructor(color = new Color(), rotation
|
|
13
|
+
constructor(color = new Color(), rotation) {
|
|
14
14
|
this.color = color;
|
|
15
15
|
this.vertexCache = new VertexCache();
|
|
16
|
-
this.is3d = is3d;
|
|
17
16
|
this.wireframe = false;
|
|
18
17
|
this.rotation = rotation;
|
|
18
|
+
this.isInstanced = false;
|
|
19
19
|
}
|
|
20
20
|
getGeometryType() {
|
|
21
21
|
return this.geometry.getType();
|
|
@@ -32,6 +32,9 @@ export class SimulationElement {
|
|
|
32
32
|
getPos() {
|
|
33
33
|
return this.pos;
|
|
34
34
|
}
|
|
35
|
+
getRotation() {
|
|
36
|
+
return this.rotation;
|
|
37
|
+
}
|
|
35
38
|
fill(newColor, t = 0, f) {
|
|
36
39
|
const diff = newColor.diff(this.color);
|
|
37
40
|
const finalColor = newColor.clone();
|
|
@@ -47,6 +50,9 @@ export class SimulationElement {
|
|
|
47
50
|
}, t, f);
|
|
48
51
|
}
|
|
49
52
|
getVertexCount() {
|
|
53
|
+
if (this.vertexCache.shouldUpdate()) {
|
|
54
|
+
this.geometry.recompute();
|
|
55
|
+
}
|
|
50
56
|
if (this.isWireframe()) {
|
|
51
57
|
return this.geometry.getWireframeVertexCount();
|
|
52
58
|
}
|
|
@@ -70,6 +76,9 @@ export class SimulationElement {
|
|
|
70
76
|
if (this.vertexCache.shouldUpdate() || camera.hasUpdated()) {
|
|
71
77
|
this.updateMatrix(camera);
|
|
72
78
|
this.geometry.recompute();
|
|
79
|
+
if (this.isInstanced) {
|
|
80
|
+
bufferGenerator.setInstancing(true);
|
|
81
|
+
}
|
|
73
82
|
let resBuffer = [];
|
|
74
83
|
if (this.isWireframe()) {
|
|
75
84
|
resBuffer = this.geometry.getWireframeBuffer(this.color);
|
|
@@ -77,6 +86,7 @@ export class SimulationElement {
|
|
|
77
86
|
else {
|
|
78
87
|
resBuffer = this.geometry.getTriangleBuffer(this.color);
|
|
79
88
|
}
|
|
89
|
+
bufferGenerator.setInstancing(false);
|
|
80
90
|
this.vertexCache.setCache(resBuffer);
|
|
81
91
|
return resBuffer;
|
|
82
92
|
}
|
|
@@ -86,6 +96,7 @@ export class SimulationElement {
|
|
|
86
96
|
export class SimulationElement3d extends SimulationElement {
|
|
87
97
|
pos;
|
|
88
98
|
rotation;
|
|
99
|
+
is3d = true;
|
|
89
100
|
constructor(pos, rotation = vector3(), color) {
|
|
90
101
|
super(color, rotation);
|
|
91
102
|
this.pos = pos;
|
|
@@ -149,7 +160,7 @@ export class SimulationElement2d extends SimulationElement {
|
|
|
149
160
|
pos;
|
|
150
161
|
rotation;
|
|
151
162
|
constructor(pos, rotation = 0, color) {
|
|
152
|
-
super(color, rotation
|
|
163
|
+
super(color, rotation);
|
|
153
164
|
this.pos = pos;
|
|
154
165
|
this.rotation = rotation;
|
|
155
166
|
}
|
|
@@ -221,15 +232,16 @@ export class Square extends SimulationElement2d {
|
|
|
221
232
|
height;
|
|
222
233
|
vertexColors;
|
|
223
234
|
/**
|
|
235
|
+
* @param centerOffset{Vector2} - A vector2 of values from 0 to 1
|
|
224
236
|
* @param vertexColors{Record<number, Color>} - 0 is top left vertex, numbers increase clockwise
|
|
225
237
|
*/
|
|
226
|
-
constructor(pos, width, height, color, rotation, vertexColors) {
|
|
238
|
+
constructor(pos, width, height, color, rotation, centerOffset, vertexColors) {
|
|
227
239
|
super(pos, rotation, color);
|
|
228
240
|
vector2ToPixelRatio(this.pos);
|
|
229
241
|
this.width = width * devicePixelRatio;
|
|
230
242
|
this.height = height * devicePixelRatio;
|
|
231
243
|
this.vertexColors = this.cloneColorMap(vertexColors || {});
|
|
232
|
-
this.geometry = new SquareGeometry(this.width, this.height);
|
|
244
|
+
this.geometry = new SquareGeometry(this.width, this.height, centerOffset);
|
|
233
245
|
this.geometry.setVertexColorMap(this.vertexColors);
|
|
234
246
|
}
|
|
235
247
|
cloneColorMap(colorMap) {
|
|
@@ -348,8 +360,6 @@ export class Square extends SimulationElement2d {
|
|
|
348
360
|
updateMatrix(camera) {
|
|
349
361
|
const pos = cloneBuf(this.pos);
|
|
350
362
|
pos[1] = camera.getScreenSize()[1] - pos[1];
|
|
351
|
-
pos[0] += this.width / 2;
|
|
352
|
-
pos[1] -= this.height / 2;
|
|
353
363
|
const matrix = matrix4();
|
|
354
364
|
mat4.translate(matrix, vector3FromVector2(pos), matrix);
|
|
355
365
|
mat4.rotateZ(matrix, this.rotation, matrix);
|
|
@@ -396,7 +406,6 @@ export class Circle extends SimulationElement2d {
|
|
|
396
406
|
this.defaultUpdateMatrix(camera);
|
|
397
407
|
}
|
|
398
408
|
}
|
|
399
|
-
// TODO: litterally this whole thing
|
|
400
409
|
export class Polygon extends SimulationElement2d {
|
|
401
410
|
geometry;
|
|
402
411
|
vertices;
|
|
@@ -753,19 +762,19 @@ export class SplinePoint2d {
|
|
|
753
762
|
}
|
|
754
763
|
export class Spline2d extends SimulationElement2d {
|
|
755
764
|
geometry;
|
|
756
|
-
curves;
|
|
757
765
|
thickness;
|
|
758
766
|
detail;
|
|
759
767
|
interpolateStart;
|
|
760
768
|
interpolateLimit;
|
|
761
769
|
constructor(pos, points, thickness = devicePixelRatio, detail = 40) {
|
|
762
|
-
|
|
763
|
-
|
|
770
|
+
const tempPos = vector2FromVector3(pos.getPos());
|
|
771
|
+
vector2ToPixelRatio(tempPos);
|
|
772
|
+
super(tempPos, 0, pos.getColor() || undefined);
|
|
764
773
|
this.thickness = thickness * devicePixelRatio;
|
|
765
774
|
this.detail = detail;
|
|
766
775
|
this.interpolateStart = 0;
|
|
767
776
|
this.interpolateLimit = 1;
|
|
768
|
-
this.geometry = new
|
|
777
|
+
this.geometry = new Spline2dGeometry(points, this.getColor(), this.thickness, this.detail);
|
|
769
778
|
}
|
|
770
779
|
setInterpolateStart(start, t = 0, f) {
|
|
771
780
|
const diff = start - this.interpolateStart;
|
|
@@ -791,13 +800,27 @@ export class Spline2d extends SimulationElement2d {
|
|
|
791
800
|
this.vertexCache.updated();
|
|
792
801
|
}, t, f);
|
|
793
802
|
}
|
|
803
|
+
setThickness(thickness, t = 0, f) {
|
|
804
|
+
thickness *= devicePixelRatio;
|
|
805
|
+
const diff = thickness - this.thickness;
|
|
806
|
+
return transitionValues((p) => {
|
|
807
|
+
this.thickness += diff * p;
|
|
808
|
+
this.geometry.updateThickness(this.thickness);
|
|
809
|
+
this.vertexCache.updated();
|
|
810
|
+
}, () => {
|
|
811
|
+
this.thickness = thickness;
|
|
812
|
+
this.geometry.updateThickness(this.thickness);
|
|
813
|
+
this.vertexCache.updated();
|
|
814
|
+
}, t, f);
|
|
815
|
+
}
|
|
794
816
|
interpolateSlope(t) {
|
|
795
|
-
const
|
|
817
|
+
const curves = this.geometry.getCurves();
|
|
818
|
+
const curveInterval = 1 / curves.length;
|
|
796
819
|
let index = Math.floor(t / curveInterval);
|
|
797
|
-
if (index ===
|
|
820
|
+
if (index === curves.length)
|
|
798
821
|
index--;
|
|
799
822
|
const diff = (t - curveInterval * index) * 2;
|
|
800
|
-
return
|
|
823
|
+
return curves[index].interpolateSlope(diff);
|
|
801
824
|
}
|
|
802
825
|
interpolate(t) {
|
|
803
826
|
const [vec] = this.interpolateSlope(t);
|
|
@@ -807,3 +830,69 @@ export class Spline2d extends SimulationElement2d {
|
|
|
807
830
|
this.defaultUpdateMatrix(camera);
|
|
808
831
|
}
|
|
809
832
|
}
|
|
833
|
+
export class Instance extends SimulationElement3d {
|
|
834
|
+
geometry;
|
|
835
|
+
obj;
|
|
836
|
+
instanceMatrix;
|
|
837
|
+
matrixBuffer;
|
|
838
|
+
device;
|
|
839
|
+
isInstance = true;
|
|
840
|
+
constructor(obj, numInstances) {
|
|
841
|
+
super(vector3());
|
|
842
|
+
this.device = null;
|
|
843
|
+
this.matrixBuffer = null;
|
|
844
|
+
obj.isInstanced = true;
|
|
845
|
+
this.obj = obj;
|
|
846
|
+
this.instanceMatrix = [];
|
|
847
|
+
this.is3d = Boolean(obj.is3d);
|
|
848
|
+
this.geometry = new BlankGeometry();
|
|
849
|
+
const mat = matrix4();
|
|
850
|
+
if (typeof obj.getRotation() === 'number') {
|
|
851
|
+
mat4.rotateZ(mat, obj.getRotation(), mat);
|
|
852
|
+
}
|
|
853
|
+
else {
|
|
854
|
+
rotateMat4(mat, obj.getRotation());
|
|
855
|
+
}
|
|
856
|
+
for (let i = 0; i < numInstances; i++) {
|
|
857
|
+
const clone = cloneBuf(mat);
|
|
858
|
+
this.instanceMatrix.push(clone);
|
|
859
|
+
}
|
|
860
|
+
}
|
|
861
|
+
setMatrixBuffer() {
|
|
862
|
+
if (!this.device || this.instanceMatrix.length === 0)
|
|
863
|
+
return;
|
|
864
|
+
this.matrixBuffer = this.device.createBuffer({
|
|
865
|
+
size: this.instanceMatrix[0].length * 4 * this.instanceMatrix.length,
|
|
866
|
+
usage: GPUBufferUsage.STORAGE,
|
|
867
|
+
mappedAtCreation: true
|
|
868
|
+
});
|
|
869
|
+
const buf = this.instanceMatrix.map((mat) => [...mat]).flat();
|
|
870
|
+
new Float32Array(this.matrixBuffer.getMappedRange()).set(buf);
|
|
871
|
+
this.matrixBuffer.unmap();
|
|
872
|
+
}
|
|
873
|
+
getInstances() {
|
|
874
|
+
return this.instanceMatrix;
|
|
875
|
+
}
|
|
876
|
+
getNumInstances() {
|
|
877
|
+
return this.instanceMatrix.length;
|
|
878
|
+
}
|
|
879
|
+
setDevice(device) {
|
|
880
|
+
this.device = device;
|
|
881
|
+
if (this.matrixBuffer === null) {
|
|
882
|
+
this.setMatrixBuffer();
|
|
883
|
+
}
|
|
884
|
+
}
|
|
885
|
+
getMatrixBuffer() {
|
|
886
|
+
return this.matrixBuffer;
|
|
887
|
+
}
|
|
888
|
+
getVertexCount() {
|
|
889
|
+
return this.obj.getVertexCount();
|
|
890
|
+
}
|
|
891
|
+
getGeometryType() {
|
|
892
|
+
return this.obj.getGeometryType();
|
|
893
|
+
}
|
|
894
|
+
updateMatrix(_) { }
|
|
895
|
+
getBuffer(camera) {
|
|
896
|
+
return this.obj.getBuffer(camera);
|
|
897
|
+
}
|
|
898
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export * from './simulation.js';
|
|
2
2
|
export * from './graphics.js';
|
|
3
3
|
export * from './types.js';
|
|
4
|
-
export {
|
|
4
|
+
export { vec2, vec3, vec4, mat3, mat4 } from 'wgpu-matrix';
|
|
5
|
+
export { Vertex, Color, cloneBuf, vector4, vector3, vector2, vector3FromVector2, colorFromVector4, randomInt, randomColor, vertex, color, colorf, transitionValues, lerp, smoothStep, linearStep, splinePoint2d, continuousSplinePoint2d, easeInOutQuad, easeInOutExpo, easeInOutQuart, waitFor, matrix4 } from './utils.js';
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export * from './simulation.js';
|
|
2
2
|
export * from './graphics.js';
|
|
3
3
|
export * from './types.js';
|
|
4
|
-
export {
|
|
4
|
+
export { vec2, vec3, vec4, mat3, mat4 } from 'wgpu-matrix';
|
|
5
|
+
export { Vertex, Color, cloneBuf, vector4, vector3, vector2, vector3FromVector2, colorFromVector4, randomInt, randomColor, vertex, color, colorf, transitionValues, lerp, smoothStep, linearStep, splinePoint2d, continuousSplinePoint2d, easeInOutQuad, easeInOutExpo, easeInOutQuart, waitFor, matrix4 } from './utils.js';
|
package/dist/simulation.d.ts
CHANGED
|
@@ -12,14 +12,15 @@ export declare class Simulation {
|
|
|
12
12
|
private frameRateView;
|
|
13
13
|
private camera;
|
|
14
14
|
private pipelines;
|
|
15
|
+
private renderInfo;
|
|
15
16
|
constructor(idOrCanvasRef: string | HTMLCanvasElement, camera?: Camera | null, showFrameRate?: boolean);
|
|
16
17
|
add(el: SimulationElement<any>): void;
|
|
17
18
|
setCanvasSize(width: number, height: number): void;
|
|
18
19
|
start(): void;
|
|
19
20
|
stop(): void;
|
|
20
21
|
setBackground(color: Color): void;
|
|
22
|
+
private propagateDevice;
|
|
21
23
|
render(device: GPUDevice, ctx: GPUCanvasContext): void;
|
|
22
|
-
private getVertexCount;
|
|
23
24
|
private renderScene;
|
|
24
25
|
fitElement(): void;
|
|
25
26
|
private assertHasCanvas;
|
|
@@ -28,6 +29,7 @@ export declare class SceneCollection extends SimulationElement3d {
|
|
|
28
29
|
protected geometry: BlankGeometry;
|
|
29
30
|
private name;
|
|
30
31
|
private scene;
|
|
32
|
+
readonly isCollection = true;
|
|
31
33
|
constructor(name: string);
|
|
32
34
|
setWireframe(_: boolean): void;
|
|
33
35
|
getName(): string;
|
package/dist/simulation.js
CHANGED
|
@@ -1,16 +1,17 @@
|
|
|
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, applyElementToScene, buildDepthTexture, buildMultisampleTexture, buildProjectionMatrix, createPipeline, getOrthoMatrix, getTransformationMatrix, logger, transitionValues, vector2, vector3 } from './utils.js';
|
|
4
|
+
import { Color, applyElementToScene, buildDepthTexture, buildMultisampleTexture, buildProjectionMatrix, createPipeline, getOrthoMatrix, getTotalVertices, getTransformationMatrix, logger, transitionValues, vector2, vector3 } from './utils.js';
|
|
5
5
|
import { BlankGeometry } from './geometry.js';
|
|
6
6
|
const shader = `
|
|
7
7
|
struct Uniforms {
|
|
8
8
|
modelViewProjectionMatrix : mat4x4<f32>,
|
|
9
|
-
orthoProjectionMatrix : mat4x4<f32
|
|
10
|
-
screenSize : vec2<f32>,
|
|
9
|
+
orthoProjectionMatrix : mat4x4<f32>
|
|
11
10
|
}
|
|
12
11
|
|
|
13
|
-
@
|
|
12
|
+
@group(0) @binding(0) var<uniform> uniforms : Uniforms;
|
|
13
|
+
|
|
14
|
+
@group(0) @binding(1) var<storage, read> instanceMatrices : array<mat4x4f, 10>;
|
|
14
15
|
|
|
15
16
|
struct VertexOutput {
|
|
16
17
|
@builtin(position) Position : vec4<f32>,
|
|
@@ -21,9 +22,11 @@ struct VertexOutput {
|
|
|
21
22
|
|
|
22
23
|
@vertex
|
|
23
24
|
fn vertex_main_3d(
|
|
25
|
+
@builtin(instance_index) instanceIdx : u32,
|
|
24
26
|
@location(0) position : vec4<f32>,
|
|
25
27
|
@location(1) color : vec4<f32>,
|
|
26
28
|
@location(2) uv : vec2<f32>,
|
|
29
|
+
@location(3) drawingInstance: f32
|
|
27
30
|
) -> VertexOutput {
|
|
28
31
|
var output : VertexOutput;
|
|
29
32
|
|
|
@@ -36,13 +39,21 @@ fn vertex_main_3d(
|
|
|
36
39
|
|
|
37
40
|
@vertex
|
|
38
41
|
fn vertex_main_2d(
|
|
42
|
+
@builtin(instance_index) instanceIdx : u32,
|
|
39
43
|
@location(0) position : vec4<f32>,
|
|
40
44
|
@location(1) color : vec4<f32>,
|
|
41
45
|
@location(2) uv : vec2<f32>,
|
|
46
|
+
@location(3) drawingInstance: f32
|
|
42
47
|
) -> VertexOutput {
|
|
43
|
-
var output
|
|
48
|
+
var output: VertexOutput;
|
|
49
|
+
|
|
50
|
+
if (drawingInstance == 1) {
|
|
51
|
+
let transformedPos = instanceMatrices[instanceIdx] * position;
|
|
52
|
+
output.Position = uniforms.orthoProjectionMatrix * transformedPos;
|
|
53
|
+
} else {
|
|
54
|
+
output.Position = uniforms.orthoProjectionMatrix * position;
|
|
55
|
+
}
|
|
44
56
|
|
|
45
|
-
output.Position = uniforms.orthoProjectionMatrix * position;
|
|
46
57
|
output.fragUV = uv;
|
|
47
58
|
output.fragPosition = position;
|
|
48
59
|
output.fragColor = color;
|
|
@@ -56,7 +67,6 @@ fn fragment_main(
|
|
|
56
67
|
@location(2) fragPosition: vec4<f32>
|
|
57
68
|
) -> @location(0) vec4<f32> {
|
|
58
69
|
return fragColor;
|
|
59
|
-
// return fragPosition;
|
|
60
70
|
}
|
|
61
71
|
`;
|
|
62
72
|
const simjsFrameRateCss = `@import url('https://fonts.googleapis.com/css2?family=Roboto+Mono&family=Roboto:wght@100&display=swap');
|
|
@@ -107,6 +117,7 @@ export class Simulation {
|
|
|
107
117
|
frameRateView;
|
|
108
118
|
camera;
|
|
109
119
|
pipelines;
|
|
120
|
+
renderInfo;
|
|
110
121
|
constructor(idOrCanvasRef, camera = null, showFrameRate = false) {
|
|
111
122
|
if (typeof idOrCanvasRef === 'string') {
|
|
112
123
|
const ref = document.getElementById(idOrCanvasRef);
|
|
@@ -135,6 +146,7 @@ export class Simulation {
|
|
|
135
146
|
this.setCanvasSize(width, height);
|
|
136
147
|
}
|
|
137
148
|
});
|
|
149
|
+
this.renderInfo = null;
|
|
138
150
|
this.pipelines = null;
|
|
139
151
|
this.frameRateView = new FrameRateView(showFrameRate);
|
|
140
152
|
this.frameRateView.updateFrameRate(1);
|
|
@@ -160,6 +172,7 @@ export class Simulation {
|
|
|
160
172
|
if (!ctx)
|
|
161
173
|
throw logger.error('Context is null');
|
|
162
174
|
const device = await adapter.requestDevice();
|
|
175
|
+
this.propagateDevice(device);
|
|
163
176
|
ctx.configure({
|
|
164
177
|
device,
|
|
165
178
|
format: 'bgra8unorm'
|
|
@@ -175,6 +188,13 @@ export class Simulation {
|
|
|
175
188
|
setBackground(color) {
|
|
176
189
|
this.bgColor = color;
|
|
177
190
|
}
|
|
191
|
+
propagateDevice(device) {
|
|
192
|
+
for (let i = 0; i < this.scene.length; i++) {
|
|
193
|
+
if (this.scene[i].isInstance) {
|
|
194
|
+
this.scene[i].setDevice(device);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
}
|
|
178
198
|
render(device, ctx) {
|
|
179
199
|
this.assertHasCanvas();
|
|
180
200
|
const canvas = this.canvasRef;
|
|
@@ -187,27 +207,60 @@ export class Simulation {
|
|
|
187
207
|
format: presentationFormat,
|
|
188
208
|
alphaMode: 'premultiplied'
|
|
189
209
|
});
|
|
190
|
-
this.pipelines = {
|
|
191
|
-
triangleList2d: createPipeline(device, shaderModule, presentationFormat, 'vertex_main_2d', 'triangle-list'),
|
|
192
|
-
triangleStrip2d: createPipeline(device, shaderModule, presentationFormat, 'vertex_main_2d', 'triangle-strip'),
|
|
193
|
-
lineStrip2d: createPipeline(device, shaderModule, presentationFormat, 'vertex_main_2d', 'line-strip'),
|
|
194
|
-
triangleList3d: createPipeline(device, shaderModule, presentationFormat, 'vertex_main_3d', 'triangle-list'),
|
|
195
|
-
triangleStrip3d: createPipeline(device, shaderModule, presentationFormat, 'vertex_main_3d', 'triangle-strip'),
|
|
196
|
-
lineStrip3d: createPipeline(device, shaderModule, presentationFormat, 'vertex_main_3d', 'line-strip')
|
|
197
|
-
};
|
|
198
210
|
const uniformBufferSize = 4 * 16 + 4 * 16 + 4 * 2 + 8; // 4x4 matrix + 4x4 matrix + vec2<f32> + 8 bc 144 is cool
|
|
199
211
|
const uniformBuffer = device.createBuffer({
|
|
200
212
|
size: uniformBufferSize,
|
|
201
213
|
usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST
|
|
202
214
|
});
|
|
215
|
+
const instanceBuffer = device.createBuffer({
|
|
216
|
+
size: 16 * 10 * 4,
|
|
217
|
+
usage: GPUBufferUsage.STORAGE
|
|
218
|
+
});
|
|
219
|
+
const bindGroupLayout = device.createBindGroupLayout({
|
|
220
|
+
entries: [
|
|
221
|
+
{
|
|
222
|
+
binding: 0,
|
|
223
|
+
visibility: GPUShaderStage.VERTEX,
|
|
224
|
+
buffer: {
|
|
225
|
+
type: 'uniform'
|
|
226
|
+
}
|
|
227
|
+
},
|
|
228
|
+
{
|
|
229
|
+
binding: 1,
|
|
230
|
+
visibility: GPUShaderStage.VERTEX,
|
|
231
|
+
buffer: {
|
|
232
|
+
type: 'read-only-storage'
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
]
|
|
236
|
+
});
|
|
237
|
+
this.renderInfo = {
|
|
238
|
+
uniformBuffer,
|
|
239
|
+
bindGroupLayout,
|
|
240
|
+
instanceBuffer
|
|
241
|
+
};
|
|
242
|
+
this.pipelines = {
|
|
243
|
+
triangleList2d: createPipeline(device, shaderModule, bindGroupLayout, presentationFormat, 'vertex_main_2d', 'triangle-list'),
|
|
244
|
+
triangleStrip2d: createPipeline(device, shaderModule, bindGroupLayout, presentationFormat, 'vertex_main_2d', 'triangle-strip'),
|
|
245
|
+
lineStrip2d: createPipeline(device, shaderModule, bindGroupLayout, presentationFormat, 'vertex_main_2d', 'line-strip'),
|
|
246
|
+
triangleList3d: createPipeline(device, shaderModule, bindGroupLayout, presentationFormat, 'vertex_main_3d', 'triangle-list'),
|
|
247
|
+
triangleStrip3d: createPipeline(device, shaderModule, bindGroupLayout, presentationFormat, 'vertex_main_3d', 'triangle-strip'),
|
|
248
|
+
lineStrip3d: createPipeline(device, shaderModule, bindGroupLayout, presentationFormat, 'vertex_main_3d', 'line-strip')
|
|
249
|
+
};
|
|
203
250
|
const uniformBindGroup = device.createBindGroup({
|
|
204
|
-
layout:
|
|
251
|
+
layout: bindGroupLayout,
|
|
205
252
|
entries: [
|
|
206
253
|
{
|
|
207
254
|
binding: 0,
|
|
208
255
|
resource: {
|
|
209
256
|
buffer: uniformBuffer
|
|
210
257
|
}
|
|
258
|
+
},
|
|
259
|
+
{
|
|
260
|
+
binding: 1,
|
|
261
|
+
resource: {
|
|
262
|
+
buffer: instanceBuffer
|
|
263
|
+
}
|
|
211
264
|
}
|
|
212
265
|
]
|
|
213
266
|
});
|
|
@@ -281,8 +334,6 @@ export class Simulation {
|
|
|
281
334
|
device.queue.writeBuffer(uniformBuffer, 0, modelViewProjectionMatrix.buffer, modelViewProjectionMatrix.byteOffset, modelViewProjectionMatrix.byteLength);
|
|
282
335
|
device.queue.writeBuffer(uniformBuffer, 4 * 16, // 4x4 matrix
|
|
283
336
|
orthoMatrix.buffer, orthoMatrix.byteOffset, orthoMatrix.byteLength);
|
|
284
|
-
device.queue.writeBuffer(uniformBuffer, 4 * 16 + 4 * 16, // 4x4 matrix + 4x4 matrix
|
|
285
|
-
screenSize.buffer, screenSize.byteOffset, screenSize.byteLength);
|
|
286
337
|
const commandEncoder = device.createCommandEncoder();
|
|
287
338
|
const passEncoder = commandEncoder.beginRenderPass(renderPassDescriptor);
|
|
288
339
|
passEncoder.setPipeline(this.pipelines.triangleList3d);
|
|
@@ -294,26 +345,17 @@ export class Simulation {
|
|
|
294
345
|
};
|
|
295
346
|
requestAnimationFrame(frame);
|
|
296
347
|
}
|
|
297
|
-
getVertexCount(scene) {
|
|
298
|
-
let total = 0;
|
|
299
|
-
for (let i = 0; i < scene.length; i++) {
|
|
300
|
-
if (scene[i] instanceof SceneCollection)
|
|
301
|
-
continue;
|
|
302
|
-
total += scene[i].getVertexCount();
|
|
303
|
-
}
|
|
304
|
-
return total;
|
|
305
|
-
}
|
|
306
348
|
async renderScene(device, passEncoder, scene) {
|
|
307
349
|
if (this.pipelines === null)
|
|
308
350
|
return;
|
|
309
|
-
let totalVertices =
|
|
351
|
+
let totalVertices = getTotalVertices(scene);
|
|
310
352
|
const vertexBuffer = device.createBuffer({
|
|
311
|
-
size: totalVertices *
|
|
353
|
+
size: totalVertices * 4 * BUF_LEN,
|
|
312
354
|
usage: GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST
|
|
313
355
|
});
|
|
314
356
|
let currentOffset = 0;
|
|
315
357
|
for (let i = 0; i < scene.length; i++) {
|
|
316
|
-
if (scene[i]
|
|
358
|
+
if (scene[i].isCollection) {
|
|
317
359
|
this.renderScene(device, passEncoder, scene[i].getScene());
|
|
318
360
|
continue;
|
|
319
361
|
}
|
|
@@ -321,8 +363,9 @@ export class Simulation {
|
|
|
321
363
|
const vertexCount = buffer.length / BUF_LEN;
|
|
322
364
|
device.queue.writeBuffer(vertexBuffer, currentOffset, buffer);
|
|
323
365
|
vertexBuffer.unmap();
|
|
366
|
+
const is3d = Boolean(scene[i].is3d);
|
|
324
367
|
if (scene[i].isWireframe()) {
|
|
325
|
-
if (
|
|
368
|
+
if (is3d) {
|
|
326
369
|
passEncoder.setPipeline(this.pipelines.lineStrip3d);
|
|
327
370
|
}
|
|
328
371
|
else {
|
|
@@ -332,7 +375,7 @@ export class Simulation {
|
|
|
332
375
|
else {
|
|
333
376
|
const type = scene[i].getGeometryType();
|
|
334
377
|
if (type === 'strip') {
|
|
335
|
-
if (
|
|
378
|
+
if (is3d) {
|
|
336
379
|
passEncoder.setPipeline(this.pipelines.triangleStrip3d);
|
|
337
380
|
}
|
|
338
381
|
else {
|
|
@@ -340,7 +383,7 @@ export class Simulation {
|
|
|
340
383
|
}
|
|
341
384
|
}
|
|
342
385
|
else if (type === 'list') {
|
|
343
|
-
if (
|
|
386
|
+
if (is3d) {
|
|
344
387
|
passEncoder.setPipeline(this.pipelines.triangleList3d);
|
|
345
388
|
}
|
|
346
389
|
else {
|
|
@@ -348,8 +391,33 @@ export class Simulation {
|
|
|
348
391
|
}
|
|
349
392
|
}
|
|
350
393
|
}
|
|
394
|
+
let instances = 1;
|
|
395
|
+
if (scene[i].isInstance) {
|
|
396
|
+
instances = scene[i].getNumInstances();
|
|
397
|
+
const buf = scene[i].getMatrixBuffer();
|
|
398
|
+
if (buf && this.renderInfo) {
|
|
399
|
+
const uniformBindGroup = device.createBindGroup({
|
|
400
|
+
layout: this.renderInfo.bindGroupLayout,
|
|
401
|
+
entries: [
|
|
402
|
+
{
|
|
403
|
+
binding: 0,
|
|
404
|
+
resource: {
|
|
405
|
+
buffer: this.renderInfo.uniformBuffer
|
|
406
|
+
}
|
|
407
|
+
},
|
|
408
|
+
{
|
|
409
|
+
binding: 1,
|
|
410
|
+
resource: {
|
|
411
|
+
buffer: buf
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
]
|
|
415
|
+
});
|
|
416
|
+
passEncoder.setBindGroup(0, uniformBindGroup);
|
|
417
|
+
}
|
|
418
|
+
}
|
|
351
419
|
passEncoder.setVertexBuffer(0, vertexBuffer, currentOffset, buffer.byteLength);
|
|
352
|
-
passEncoder.draw(vertexCount);
|
|
420
|
+
passEncoder.draw(vertexCount, instances, 0, 0);
|
|
353
421
|
currentOffset += buffer.byteLength;
|
|
354
422
|
}
|
|
355
423
|
}
|
|
@@ -373,6 +441,7 @@ export class SceneCollection extends SimulationElement3d {
|
|
|
373
441
|
geometry;
|
|
374
442
|
name;
|
|
375
443
|
scene;
|
|
444
|
+
isCollection = true;
|
|
376
445
|
constructor(name) {
|
|
377
446
|
super(vector3());
|
|
378
447
|
this.wireframe = false;
|
|
@@ -400,7 +469,6 @@ export class SceneCollection extends SimulationElement3d {
|
|
|
400
469
|
return this.getSceneBuffer(camera);
|
|
401
470
|
}
|
|
402
471
|
getTriangles(camera) {
|
|
403
|
-
console.log('here');
|
|
404
472
|
return this.getSceneBuffer(camera);
|
|
405
473
|
}
|
|
406
474
|
updateMatrix(camera) {
|
package/dist/types.d.ts
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
/// <reference types="dist" />
|
|
2
2
|
import { CubicBezierCurve2d, SplinePoint2d } from './graphics.js';
|
|
3
3
|
import { Color, Vertex } from './utils.js';
|
|
4
|
-
export type
|
|
5
|
-
export type
|
|
6
|
-
export type
|
|
7
|
-
export type
|
|
4
|
+
export type FloatArray = Float32Array | Float64Array;
|
|
5
|
+
export type Vector4 = FloatArray & [number, number, number, number];
|
|
6
|
+
export type Vector3 = FloatArray & [number, number, number];
|
|
7
|
+
export type Vector2 = FloatArray & [number, number];
|
|
8
|
+
export type Mat4 = FloatArray & [
|
|
8
9
|
number,
|
|
9
10
|
number,
|
|
10
11
|
number,
|
|
@@ -34,12 +35,13 @@ export type SquareGeometryParams = {
|
|
|
34
35
|
width: number;
|
|
35
36
|
height: number;
|
|
36
37
|
colorMap: VertexColorMap;
|
|
38
|
+
centerOffset: Vector2;
|
|
37
39
|
};
|
|
38
40
|
export type CircleGeometryParams = {
|
|
39
41
|
radius: number;
|
|
40
42
|
detail: number;
|
|
41
43
|
};
|
|
42
|
-
export type
|
|
44
|
+
export type Spline2dGeometryParams = {
|
|
43
45
|
points: SplinePoint2d[];
|
|
44
46
|
curves: CubicBezierCurve2d[];
|
|
45
47
|
distance: number;
|
|
@@ -68,3 +70,8 @@ export type PipelineGroup = {
|
|
|
68
70
|
triangleStrip3d: GPURenderPipeline;
|
|
69
71
|
lineStrip3d: GPURenderPipeline;
|
|
70
72
|
};
|
|
73
|
+
export type RenderInfo = {
|
|
74
|
+
uniformBuffer: GPUBuffer;
|
|
75
|
+
instanceBuffer: GPUBuffer;
|
|
76
|
+
bindGroupLayout: GPUBindGroupLayout;
|
|
77
|
+
};
|
package/dist/utils.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/// <reference types="dist" />
|
|
2
2
|
import { SimulationElement, SplinePoint2d } from './graphics.js';
|
|
3
|
-
import { Mat4, Vector2, Vector3, Vector4 } from './types.js';
|
|
3
|
+
import { FloatArray, Mat4, Vector2, Vector3, Vector4 } from './types.js';
|
|
4
4
|
export declare class Color {
|
|
5
5
|
r: number;
|
|
6
6
|
g: number;
|
|
@@ -76,10 +76,16 @@ export declare function linearStep(t: number): number;
|
|
|
76
76
|
export declare function easeInOutExpo(t: number): number;
|
|
77
77
|
export declare function easeInOutQuart(t: number): number;
|
|
78
78
|
export declare function easeInOutQuad(t: number): number;
|
|
79
|
-
|
|
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;
|
|
80
86
|
export declare function vector3ToPixelRatio(vec: Vector3): void;
|
|
81
87
|
export declare function vector2ToPixelRatio(vec: Vector2): void;
|
|
82
|
-
export declare function cloneBuf<T extends
|
|
88
|
+
export declare function cloneBuf<T extends FloatArray>(buf: T): T;
|
|
83
89
|
export declare function vector4(x?: number, y?: number, z?: number, w?: number): Vector4;
|
|
84
90
|
export declare function vector3(x?: number, y?: number, z?: number): Vector3;
|
|
85
91
|
export declare function vector2(x?: number, y?: number): Vector2;
|
|
@@ -101,6 +107,7 @@ export declare function interpolateColors(colors: Color[], t: number): Color;
|
|
|
101
107
|
export declare function waitFor(t: number): Promise<unknown>;
|
|
102
108
|
export declare function matrixFromRotation(rotation: Vector3): Mat4;
|
|
103
109
|
export declare function rotateMat4(mat: Mat4, rotation: Vector3): void;
|
|
104
|
-
export declare function createPipeline(device: GPUDevice, module: GPUShaderModule, presentationFormat: GPUTextureFormat, entryPoint: string, topology: GPUPrimitiveTopology): GPURenderPipeline;
|
|
110
|
+
export declare function createPipeline(device: GPUDevice, module: GPUShaderModule, bindGroupLayout: GPUBindGroupLayout, presentationFormat: GPUTextureFormat, entryPoint: string, topology: GPUPrimitiveTopology): GPURenderPipeline;
|
|
105
111
|
export declare function triangulateWireFrameOrder(len: number): number[];
|
|
112
|
+
export declare function getTotalVertices(scene: SimulationElement[]): number;
|
|
106
113
|
export {};
|
package/dist/utils.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { mat4, vec2, vec3, vec4 } from 'wgpu-matrix';
|
|
2
2
|
import { SimulationElement, SplinePoint2d } from './graphics.js';
|
|
3
|
-
import { BUF_LEN, colorOffset, uvOffset, vertexSize } from './constants.js';
|
|
3
|
+
import { BUF_LEN, colorOffset, drawingInstancesOffset, uvOffset, vertexSize } from './constants.js';
|
|
4
4
|
export class Color {
|
|
5
5
|
r; // 0 - 255
|
|
6
6
|
g; // 0 - 255
|
|
@@ -100,9 +100,9 @@ export class Vertex {
|
|
|
100
100
|
}
|
|
101
101
|
toBuffer(defaultColor) {
|
|
102
102
|
if (this.is3d)
|
|
103
|
-
return
|
|
103
|
+
return bufferGenerator.generate(this.pos[0], this.pos[1], this.pos[2], this.color || defaultColor, this.uv);
|
|
104
104
|
else
|
|
105
|
-
return
|
|
105
|
+
return bufferGenerator.generate(this.pos[0], this.pos[1], 0, this.color || defaultColor, this.uv);
|
|
106
106
|
}
|
|
107
107
|
}
|
|
108
108
|
export const buildProjectionMatrix = (aspectRatio, zNear = 1, zFar = 500) => {
|
|
@@ -143,7 +143,7 @@ export const buildMultisampleTexture = (device, ctx, width, height) => {
|
|
|
143
143
|
};
|
|
144
144
|
export const applyElementToScene = (scene, el) => {
|
|
145
145
|
if (el instanceof SimulationElement) {
|
|
146
|
-
scene.
|
|
146
|
+
scene.unshift(el);
|
|
147
147
|
}
|
|
148
148
|
else {
|
|
149
149
|
throw logger.error('Cannot add invalid SimulationElement');
|
|
@@ -260,9 +260,17 @@ export function easeInOutQuart(t) {
|
|
|
260
260
|
export function easeInOutQuad(t) {
|
|
261
261
|
return t < 0.5 ? 2 * t * t : 1 - Math.pow(-2 * t + 2, 2) / 2;
|
|
262
262
|
}
|
|
263
|
-
|
|
264
|
-
|
|
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
|
+
}
|
|
265
272
|
}
|
|
273
|
+
export const bufferGenerator = new BufferGenerator();
|
|
266
274
|
export function vector3ToPixelRatio(vec) {
|
|
267
275
|
vec[0] *= devicePixelRatio;
|
|
268
276
|
vec[1] *= devicePixelRatio;
|
|
@@ -371,9 +379,11 @@ export function rotateMat4(mat, rotation) {
|
|
|
371
379
|
mat4.rotateY(mat, rotation[1], mat);
|
|
372
380
|
mat4.rotateX(mat, rotation[0], mat);
|
|
373
381
|
}
|
|
374
|
-
export function createPipeline(device, module, presentationFormat, entryPoint, topology) {
|
|
382
|
+
export function createPipeline(device, module, bindGroupLayout, presentationFormat, entryPoint, topology) {
|
|
375
383
|
return device.createRenderPipeline({
|
|
376
|
-
layout:
|
|
384
|
+
layout: device.createPipelineLayout({
|
|
385
|
+
bindGroupLayouts: [bindGroupLayout]
|
|
386
|
+
}),
|
|
377
387
|
vertex: {
|
|
378
388
|
module,
|
|
379
389
|
entryPoint,
|
|
@@ -398,6 +408,12 @@ export function createPipeline(device, module, presentationFormat, entryPoint, t
|
|
|
398
408
|
shaderLocation: 2,
|
|
399
409
|
offset: uvOffset,
|
|
400
410
|
format: 'float32x2'
|
|
411
|
+
},
|
|
412
|
+
{
|
|
413
|
+
// drawing instances
|
|
414
|
+
shaderLocation: 3,
|
|
415
|
+
offset: drawingInstancesOffset,
|
|
416
|
+
format: 'float32'
|
|
401
417
|
}
|
|
402
418
|
]
|
|
403
419
|
}
|
|
@@ -438,3 +454,12 @@ export function triangulateWireFrameOrder(len) {
|
|
|
438
454
|
}
|
|
439
455
|
return order;
|
|
440
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;
|
|
465
|
+
}
|