simulationjsv2 0.6.0 → 0.7.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/TODO.md +9 -5
- package/dist/constants.d.ts +1 -0
- package/dist/constants.js +1 -0
- package/dist/geometry.d.ts +11 -1
- package/dist/geometry.js +31 -0
- package/dist/graphics.d.ts +70 -19
- package/dist/graphics.js +274 -101
- package/dist/internalUtils.d.ts +9 -8
- package/dist/internalUtils.js +33 -44
- package/dist/settings.d.ts +7 -0
- package/dist/settings.js +9 -0
- package/dist/simulation.d.ts +30 -69
- package/dist/simulation.js +145 -261
- package/dist/types.d.ts +4 -0
- package/dist/utils.d.ts +8 -8
- package/dist/utils.js +13 -19
- package/package.json +1 -1
package/dist/simulation.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { vec3 } from 'wgpu-matrix';
|
|
2
|
-
import {
|
|
2
|
+
import { EmptyElement, SimulationElement3d } from './graphics.js';
|
|
3
3
|
import { BUF_LEN, worldProjMatOffset } from './constants.js';
|
|
4
|
-
import { Color, matrix4,
|
|
4
|
+
import { Color, matrix4, transitionValues, vector2, vector3 } from './utils.js';
|
|
5
5
|
import { BlankGeometry } from './geometry.js';
|
|
6
|
-
import {
|
|
6
|
+
import { SimSceneObjInfo, buildDepthTexture, buildMultisampleTexture, updateProjectionMatrix, createPipeline, getTotalVertices, logger, removeObjectId, updateOrthoProjectionMatrix, updateWorldProjectionMatrix } from './internalUtils.js';
|
|
7
|
+
import { Settings } from './settings.js';
|
|
7
8
|
const shader = `
|
|
8
9
|
struct Uniforms {
|
|
9
10
|
worldProjectionMatrix: mat4x4<f32>,
|
|
@@ -31,6 +32,7 @@ fn vertex_main(
|
|
|
31
32
|
) -> VertexOutput {
|
|
32
33
|
var output: VertexOutput;
|
|
33
34
|
|
|
35
|
+
|
|
34
36
|
if (drawingInstance == 1) {
|
|
35
37
|
output.Position = uniforms.worldProjectionMatrix * uniforms.modelProjectionMatrix * instanceMatrices[instanceIdx] * vec4(position, 1.0);
|
|
36
38
|
} else {
|
|
@@ -115,7 +117,95 @@ let aspectRatio = 0;
|
|
|
115
117
|
const projMat = matrix4();
|
|
116
118
|
const worldProjMat = matrix4();
|
|
117
119
|
const orthoMatrix = matrix4();
|
|
118
|
-
export class
|
|
120
|
+
export class Camera {
|
|
121
|
+
pos;
|
|
122
|
+
rotation;
|
|
123
|
+
aspectRatio = 1;
|
|
124
|
+
updated;
|
|
125
|
+
screenSize = vector2();
|
|
126
|
+
constructor(pos, rotation = vector3()) {
|
|
127
|
+
this.pos = pos;
|
|
128
|
+
this.updated = false;
|
|
129
|
+
this.rotation = rotation;
|
|
130
|
+
}
|
|
131
|
+
setScreenSize(size) {
|
|
132
|
+
this.screenSize = size;
|
|
133
|
+
this.aspectRatio = size[0] / size[1];
|
|
134
|
+
this.updated = true;
|
|
135
|
+
}
|
|
136
|
+
getScreenSize() {
|
|
137
|
+
return this.screenSize;
|
|
138
|
+
}
|
|
139
|
+
hasUpdated() {
|
|
140
|
+
return this.updated;
|
|
141
|
+
}
|
|
142
|
+
updateConsumed() {
|
|
143
|
+
this.updated = false;
|
|
144
|
+
}
|
|
145
|
+
move(amount, t = 0, f) {
|
|
146
|
+
const initial = vector3();
|
|
147
|
+
vec3.clone(this.pos, initial);
|
|
148
|
+
return transitionValues((p) => {
|
|
149
|
+
const x = amount[0] * p;
|
|
150
|
+
const y = amount[1] * p;
|
|
151
|
+
const z = amount[2] * p;
|
|
152
|
+
const diff = vector3(x, y, z);
|
|
153
|
+
vec3.add(this.pos, diff, this.pos);
|
|
154
|
+
}, () => {
|
|
155
|
+
vec3.add(initial, amount, this.pos);
|
|
156
|
+
}, t, f);
|
|
157
|
+
}
|
|
158
|
+
moveTo(pos, t = 0, f) {
|
|
159
|
+
const diff = vector3();
|
|
160
|
+
vec3.sub(pos, this.pos, diff);
|
|
161
|
+
return transitionValues((p) => {
|
|
162
|
+
const x = diff[0] * p;
|
|
163
|
+
const y = diff[1] * p;
|
|
164
|
+
const z = diff[2] * p;
|
|
165
|
+
const amount = vector3(x, y, z);
|
|
166
|
+
vec3.add(this.pos, amount, this.pos);
|
|
167
|
+
}, () => {
|
|
168
|
+
vec3.clone(pos, this.pos);
|
|
169
|
+
}, t, f);
|
|
170
|
+
}
|
|
171
|
+
rotateTo(value, t = 0, f) {
|
|
172
|
+
const diff = vec3.clone(value);
|
|
173
|
+
vec3.sub(diff, diff, this.rotation);
|
|
174
|
+
return transitionValues((p) => {
|
|
175
|
+
const x = diff[0] * p;
|
|
176
|
+
const y = diff[1] * p;
|
|
177
|
+
const z = diff[2] * p;
|
|
178
|
+
vec3.add(this.rotation, this.rotation, vector3(x, y, z));
|
|
179
|
+
this.updated = true;
|
|
180
|
+
}, () => {
|
|
181
|
+
this.rotation = value;
|
|
182
|
+
}, t, f);
|
|
183
|
+
}
|
|
184
|
+
rotate(amount, t = 0, f) {
|
|
185
|
+
const initial = vector3();
|
|
186
|
+
vec3.clone(this.rotation, initial);
|
|
187
|
+
return transitionValues((p) => {
|
|
188
|
+
const x = amount[0] * p;
|
|
189
|
+
const y = amount[1] * p;
|
|
190
|
+
const z = amount[2] * p;
|
|
191
|
+
vec3.add(this.rotation, vector3(x, y, z), this.rotation);
|
|
192
|
+
this.updated = true;
|
|
193
|
+
}, () => {
|
|
194
|
+
vec3.add(initial, amount, this.rotation);
|
|
195
|
+
}, t, f);
|
|
196
|
+
}
|
|
197
|
+
getRotation() {
|
|
198
|
+
return this.rotation;
|
|
199
|
+
}
|
|
200
|
+
getPos() {
|
|
201
|
+
return this.pos;
|
|
202
|
+
}
|
|
203
|
+
getAspectRatio() {
|
|
204
|
+
return this.aspectRatio;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
export let camera = new Camera(vector3());
|
|
208
|
+
export class Simulation extends Settings {
|
|
119
209
|
canvasRef = null;
|
|
120
210
|
bgColor = new Color(255, 255, 255);
|
|
121
211
|
scene = [];
|
|
@@ -123,12 +213,12 @@ export class Simulation {
|
|
|
123
213
|
running = true;
|
|
124
214
|
initialized = false;
|
|
125
215
|
frameRateView;
|
|
126
|
-
camera;
|
|
127
216
|
device = null;
|
|
128
217
|
pipelines = null;
|
|
129
218
|
renderInfo = null;
|
|
130
219
|
resizeEvents;
|
|
131
|
-
constructor(idOrCanvasRef,
|
|
220
|
+
constructor(idOrCanvasRef, sceneCamera = null, showFrameRate = false) {
|
|
221
|
+
super();
|
|
132
222
|
if (typeof idOrCanvasRef === 'string') {
|
|
133
223
|
const ref = document.getElementById(idOrCanvasRef);
|
|
134
224
|
if (ref !== null)
|
|
@@ -143,10 +233,9 @@ export class Simulation {
|
|
|
143
233
|
throw logger.error(`Canvas ref/id provided is invalid`);
|
|
144
234
|
}
|
|
145
235
|
const parent = this.canvasRef.parentElement;
|
|
146
|
-
if (
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
this.camera = camera;
|
|
236
|
+
if (sceneCamera) {
|
|
237
|
+
camera = sceneCamera;
|
|
238
|
+
}
|
|
150
239
|
if (parent === null)
|
|
151
240
|
throw logger.error('Canvas parent is null');
|
|
152
241
|
this.resizeEvents = [];
|
|
@@ -173,10 +262,24 @@ export class Simulation {
|
|
|
173
262
|
return (this.canvasRef?.height || 0) / devicePixelRatio;
|
|
174
263
|
}
|
|
175
264
|
add(el, id) {
|
|
176
|
-
|
|
265
|
+
if (el instanceof SimulationElement3d) {
|
|
266
|
+
if (this.device !== null) {
|
|
267
|
+
el.propagateDevice(this.device);
|
|
268
|
+
}
|
|
269
|
+
const obj = new SimSceneObjInfo(el, id);
|
|
270
|
+
this.scene.unshift(obj);
|
|
271
|
+
}
|
|
272
|
+
else {
|
|
273
|
+
throw logger.error('Cannot add invalid SimulationElement');
|
|
274
|
+
}
|
|
177
275
|
}
|
|
178
276
|
remove(el) {
|
|
179
|
-
|
|
277
|
+
for (let i = 0; i < this.scene.length; i++) {
|
|
278
|
+
if (this.scene[i].getObj() === el) {
|
|
279
|
+
this.scene.splice(i, 1);
|
|
280
|
+
break;
|
|
281
|
+
}
|
|
282
|
+
}
|
|
180
283
|
}
|
|
181
284
|
removeId(id) {
|
|
182
285
|
removeObjectId(this.scene, id);
|
|
@@ -228,16 +331,14 @@ export class Simulation {
|
|
|
228
331
|
format: 'bgra8unorm'
|
|
229
332
|
});
|
|
230
333
|
const screenSize = vector2(this.canvasRef.width, this.canvasRef.height);
|
|
231
|
-
|
|
334
|
+
camera.setScreenSize(screenSize);
|
|
232
335
|
this.render(ctx);
|
|
233
336
|
})();
|
|
234
337
|
}
|
|
235
338
|
propagateDevice(device) {
|
|
236
339
|
for (let i = 0; i < this.scene.length; i++) {
|
|
237
340
|
const el = this.scene[i].getObj();
|
|
238
|
-
|
|
239
|
-
el.setDevice(device);
|
|
240
|
-
}
|
|
341
|
+
el.propagateDevice(device);
|
|
241
342
|
}
|
|
242
343
|
}
|
|
243
344
|
stop() {
|
|
@@ -294,8 +395,8 @@ export class Simulation {
|
|
|
294
395
|
updateProjectionMatrix(projMat, newAspectRatio);
|
|
295
396
|
aspectRatio = newAspectRatio;
|
|
296
397
|
}
|
|
297
|
-
updateWorldProjectionMatrix(worldProjMat, projMat
|
|
298
|
-
updateOrthoProjectionMatrix(orthoMatrix,
|
|
398
|
+
updateWorldProjectionMatrix(worldProjMat, projMat);
|
|
399
|
+
updateOrthoProjectionMatrix(orthoMatrix, camera.getScreenSize());
|
|
299
400
|
let multisampleTexture = buildMultisampleTexture(device, ctx, canvas.width, canvas.height);
|
|
300
401
|
let depthTexture = buildDepthTexture(device, canvas.width, canvas.height);
|
|
301
402
|
const renderPassDescriptor = {
|
|
@@ -328,14 +429,14 @@ export class Simulation {
|
|
|
328
429
|
prevFps = fps;
|
|
329
430
|
canvas.width = canvas.clientWidth * devicePixelRatio;
|
|
330
431
|
canvas.height = canvas.clientHeight * devicePixelRatio;
|
|
331
|
-
const screenSize =
|
|
432
|
+
const screenSize = camera.getScreenSize();
|
|
332
433
|
if (screenSize[0] !== canvas.width || screenSize[1] !== canvas.height) {
|
|
333
|
-
|
|
434
|
+
camera.setScreenSize(vector2(canvas.width, canvas.height));
|
|
334
435
|
screenSize[0] = canvas.width;
|
|
335
436
|
screenSize[1] = canvas.height;
|
|
336
|
-
aspectRatio =
|
|
437
|
+
aspectRatio = camera.getAspectRatio();
|
|
337
438
|
updateProjectionMatrix(projMat, aspectRatio);
|
|
338
|
-
updateWorldProjectionMatrix(worldProjMat, projMat
|
|
439
|
+
updateWorldProjectionMatrix(worldProjMat, projMat);
|
|
339
440
|
multisampleTexture = buildMultisampleTexture(device, ctx, screenSize[0], screenSize[1]);
|
|
340
441
|
depthTexture = buildDepthTexture(device, screenSize[0], screenSize[1]);
|
|
341
442
|
renderPassDescriptor.depthStencilAttachment.view = depthTexture.createView();
|
|
@@ -346,9 +447,9 @@ export class Simulation {
|
|
|
346
447
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
347
448
|
// @ts-ignore
|
|
348
449
|
renderPassDescriptor.colorAttachments[0].resolveTarget = ctx.getCurrentTexture().createView();
|
|
349
|
-
if (
|
|
350
|
-
updateOrthoProjectionMatrix(orthoMatrix,
|
|
351
|
-
updateWorldProjectionMatrix(worldProjMat, projMat
|
|
450
|
+
if (camera.hasUpdated()) {
|
|
451
|
+
updateOrthoProjectionMatrix(orthoMatrix, camera.getScreenSize());
|
|
452
|
+
updateWorldProjectionMatrix(worldProjMat, projMat);
|
|
352
453
|
}
|
|
353
454
|
const commandEncoder = device.createCommandEncoder();
|
|
354
455
|
const passEncoder = commandEncoder.beginRenderPass(renderPassDescriptor);
|
|
@@ -362,7 +463,7 @@ export class Simulation {
|
|
|
362
463
|
});
|
|
363
464
|
}
|
|
364
465
|
this.renderScene(device, passEncoder, this.renderInfo.vertexBuffer, this.scene, 0, diff);
|
|
365
|
-
|
|
466
|
+
camera.updateConsumed();
|
|
366
467
|
passEncoder.end();
|
|
367
468
|
device.queue.submit([commandEncoder.finish()]);
|
|
368
469
|
};
|
|
@@ -384,7 +485,7 @@ export class Simulation {
|
|
|
384
485
|
scene[i].traverseLife(diff);
|
|
385
486
|
}
|
|
386
487
|
const obj = scene[i].getObj();
|
|
387
|
-
if (obj
|
|
488
|
+
if (obj.hasChildren()) {
|
|
388
489
|
let shaderInfo = undefined;
|
|
389
490
|
if (obj instanceof ShaderGroup) {
|
|
390
491
|
const pipeline = obj.getPipeline();
|
|
@@ -394,30 +495,27 @@ export class Simulation {
|
|
|
394
495
|
paramGenerator: obj.getVertexParamGenerator(),
|
|
395
496
|
bufferInfo: obj.hasBindGroup()
|
|
396
497
|
? {
|
|
397
|
-
buffers: obj.getBindGroupBuffers(),
|
|
498
|
+
buffers: obj.getBindGroupBuffers(device),
|
|
398
499
|
layout: obj.getBindGroupLayout()
|
|
399
500
|
}
|
|
400
501
|
: null
|
|
401
502
|
};
|
|
402
503
|
}
|
|
403
504
|
}
|
|
404
|
-
currentOffset += this.renderScene(device, passEncoder, vertexBuffer, obj.
|
|
405
|
-
continue;
|
|
505
|
+
currentOffset += this.renderScene(device, passEncoder, vertexBuffer, obj.getChildrenInfos(), currentOffset, diff, shaderInfo);
|
|
406
506
|
}
|
|
507
|
+
if (obj.isEmpty)
|
|
508
|
+
continue;
|
|
407
509
|
const buffer = new Float32Array(obj.getBuffer(shaderInfo?.paramGenerator));
|
|
408
510
|
const bufLen = shaderInfo?.paramGenerator?.bufferSize || BUF_LEN;
|
|
409
511
|
const vertexCount = buffer.length / bufLen;
|
|
410
|
-
device.queue.writeBuffer(vertexBuffer, currentOffset, buffer);
|
|
512
|
+
device.queue.writeBuffer(vertexBuffer, currentOffset, buffer.buffer, buffer.byteOffset, buffer.byteLength);
|
|
411
513
|
vertexBuffer.unmap();
|
|
412
514
|
passEncoder.setVertexBuffer(0, vertexBuffer, currentOffset, buffer.byteLength);
|
|
413
|
-
const modelMatrix = obj.getModelMatrix(
|
|
515
|
+
const modelMatrix = obj.getModelMatrix();
|
|
414
516
|
const uniformBuffer = obj.getUniformBuffer(device, modelMatrix);
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
}
|
|
418
|
-
else {
|
|
419
|
-
device.queue.writeBuffer(uniformBuffer, worldProjMatOffset, orthoMatrix.buffer, orthoMatrix.byteOffset, orthoMatrix.byteLength);
|
|
420
|
-
}
|
|
517
|
+
const projBuf = obj.is3d ? worldProjMat : orthoMatrix;
|
|
518
|
+
device.queue.writeBuffer(uniformBuffer, worldProjMatOffset, projBuf.buffer, projBuf.byteOffset, projBuf.byteLength);
|
|
421
519
|
if (shaderInfo) {
|
|
422
520
|
passEncoder.setPipeline(shaderInfo.pipeline);
|
|
423
521
|
}
|
|
@@ -436,7 +534,7 @@ export class Simulation {
|
|
|
436
534
|
let instances = 1;
|
|
437
535
|
if (this.renderInfo) {
|
|
438
536
|
let instanceBuffer;
|
|
439
|
-
if (obj
|
|
537
|
+
if (obj.isInstance) {
|
|
440
538
|
instances = obj.getNumInstances();
|
|
441
539
|
instanceBuffer = obj.getMatrixBuffer(device);
|
|
442
540
|
}
|
|
@@ -480,7 +578,7 @@ export class Simulation {
|
|
|
480
578
|
currentOffset += buffer.byteLength;
|
|
481
579
|
}
|
|
482
580
|
for (let i = toRemove.length - 1; i >= 0; i--) {
|
|
483
|
-
|
|
581
|
+
this.remove(scene[i].getObj());
|
|
484
582
|
}
|
|
485
583
|
return currentOffset - startOffset;
|
|
486
584
|
}
|
|
@@ -496,179 +594,6 @@ export class Simulation {
|
|
|
496
594
|
}
|
|
497
595
|
}
|
|
498
596
|
}
|
|
499
|
-
export class SceneCollection extends SimulationElement3d {
|
|
500
|
-
geometry;
|
|
501
|
-
name;
|
|
502
|
-
scene;
|
|
503
|
-
device = null;
|
|
504
|
-
constructor(name) {
|
|
505
|
-
super(vector3());
|
|
506
|
-
this.wireframe = false;
|
|
507
|
-
this.name = name || null;
|
|
508
|
-
this.scene = [];
|
|
509
|
-
this.geometry = new BlankGeometry();
|
|
510
|
-
}
|
|
511
|
-
setWireframe(wireframe) {
|
|
512
|
-
this.wireframe = wireframe;
|
|
513
|
-
for (let i = 0; i < this.scene.length; i++) {
|
|
514
|
-
this.scene[i].getObj().setWireframe(wireframe);
|
|
515
|
-
}
|
|
516
|
-
}
|
|
517
|
-
getName() {
|
|
518
|
-
return this.name;
|
|
519
|
-
}
|
|
520
|
-
getScene() {
|
|
521
|
-
return this.scene;
|
|
522
|
-
}
|
|
523
|
-
setDevice(device) {
|
|
524
|
-
this.device = device;
|
|
525
|
-
this.propagateDevice(device);
|
|
526
|
-
}
|
|
527
|
-
propagateDevice(device) {
|
|
528
|
-
for (let i = 0; i < this.scene.length; i++) {
|
|
529
|
-
const el = this.scene[i].getObj();
|
|
530
|
-
if (el instanceof SceneCollection) {
|
|
531
|
-
el.setDevice(device);
|
|
532
|
-
}
|
|
533
|
-
}
|
|
534
|
-
}
|
|
535
|
-
getVertexCount() {
|
|
536
|
-
let total = 0;
|
|
537
|
-
for (let i = 0; i < this.scene.length; i++) {
|
|
538
|
-
total += this.scene[i].getObj().getVertexCount();
|
|
539
|
-
}
|
|
540
|
-
return total;
|
|
541
|
-
}
|
|
542
|
-
getSceneObjects() {
|
|
543
|
-
return this.scene.map((item) => item.getObj());
|
|
544
|
-
}
|
|
545
|
-
setSceneObjects(newScene) {
|
|
546
|
-
this.scene = toSceneObjInfoMany(newScene);
|
|
547
|
-
}
|
|
548
|
-
setScene(newScene) {
|
|
549
|
-
this.scene = newScene;
|
|
550
|
-
}
|
|
551
|
-
add(el, id) {
|
|
552
|
-
addObject(this.scene, el, this.device, id);
|
|
553
|
-
}
|
|
554
|
-
remove(el) {
|
|
555
|
-
removeObject(this.scene, el);
|
|
556
|
-
}
|
|
557
|
-
removeId(id) {
|
|
558
|
-
removeObjectId(this.scene, id);
|
|
559
|
-
}
|
|
560
|
-
/**
|
|
561
|
-
* @param lifetime - ms
|
|
562
|
-
*/
|
|
563
|
-
setLifetime(el, lifetime) {
|
|
564
|
-
for (let i = 0; i < this.scene.length; i++) {
|
|
565
|
-
if (this.scene[i].getObj() === el)
|
|
566
|
-
this.scene[i].setLifetime(lifetime);
|
|
567
|
-
}
|
|
568
|
-
}
|
|
569
|
-
empty() {
|
|
570
|
-
this.scene = [];
|
|
571
|
-
}
|
|
572
|
-
getSceneBuffer() {
|
|
573
|
-
return this.scene.map((item) => item.getObj().getBuffer()).flat();
|
|
574
|
-
}
|
|
575
|
-
getWireframe() {
|
|
576
|
-
return this.getSceneBuffer();
|
|
577
|
-
}
|
|
578
|
-
getTriangles() {
|
|
579
|
-
return this.getSceneBuffer();
|
|
580
|
-
}
|
|
581
|
-
updateMatrix(camera) {
|
|
582
|
-
this.defaultUpdateMatrix(camera);
|
|
583
|
-
}
|
|
584
|
-
}
|
|
585
|
-
export class Camera {
|
|
586
|
-
pos;
|
|
587
|
-
rotation;
|
|
588
|
-
aspectRatio = 1;
|
|
589
|
-
updated;
|
|
590
|
-
screenSize = vector2();
|
|
591
|
-
constructor(pos, rotation = vector3()) {
|
|
592
|
-
this.pos = pos;
|
|
593
|
-
this.updated = false;
|
|
594
|
-
this.rotation = rotation;
|
|
595
|
-
}
|
|
596
|
-
setScreenSize(size) {
|
|
597
|
-
this.screenSize = size;
|
|
598
|
-
this.aspectRatio = size[0] / size[1];
|
|
599
|
-
this.updated = true;
|
|
600
|
-
}
|
|
601
|
-
getScreenSize() {
|
|
602
|
-
return this.screenSize;
|
|
603
|
-
}
|
|
604
|
-
hasUpdated() {
|
|
605
|
-
return this.updated;
|
|
606
|
-
}
|
|
607
|
-
updateConsumed() {
|
|
608
|
-
this.updated = false;
|
|
609
|
-
}
|
|
610
|
-
move(amount, t = 0, f) {
|
|
611
|
-
const initial = vector3();
|
|
612
|
-
vec3.clone(this.pos, initial);
|
|
613
|
-
return transitionValues((p) => {
|
|
614
|
-
const x = amount[0] * p;
|
|
615
|
-
const y = amount[1] * p;
|
|
616
|
-
const z = amount[2] * p;
|
|
617
|
-
const diff = vector3(x, y, z);
|
|
618
|
-
vec3.add(this.pos, diff, this.pos);
|
|
619
|
-
}, () => {
|
|
620
|
-
vec3.add(initial, amount, this.pos);
|
|
621
|
-
}, t, f);
|
|
622
|
-
}
|
|
623
|
-
moveTo(pos, t = 0, f) {
|
|
624
|
-
const diff = vector3();
|
|
625
|
-
vec3.sub(pos, this.pos, diff);
|
|
626
|
-
return transitionValues((p) => {
|
|
627
|
-
const x = diff[0] * p;
|
|
628
|
-
const y = diff[1] * p;
|
|
629
|
-
const z = diff[2] * p;
|
|
630
|
-
const amount = vector3(x, y, z);
|
|
631
|
-
vec3.add(this.pos, amount, this.pos);
|
|
632
|
-
}, () => {
|
|
633
|
-
vec3.clone(pos, this.pos);
|
|
634
|
-
}, t, f);
|
|
635
|
-
}
|
|
636
|
-
rotateTo(value, t = 0, f) {
|
|
637
|
-
const diff = vec3.clone(value);
|
|
638
|
-
vec3.sub(diff, diff, this.rotation);
|
|
639
|
-
return transitionValues((p) => {
|
|
640
|
-
const x = diff[0] * p;
|
|
641
|
-
const y = diff[1] * p;
|
|
642
|
-
const z = diff[2] * p;
|
|
643
|
-
vec3.add(this.rotation, this.rotation, vector3(x, y, z));
|
|
644
|
-
this.updated = true;
|
|
645
|
-
}, () => {
|
|
646
|
-
this.rotation = value;
|
|
647
|
-
}, t, f);
|
|
648
|
-
}
|
|
649
|
-
rotate(amount, t = 0, f) {
|
|
650
|
-
const initial = vector3();
|
|
651
|
-
vec3.clone(this.rotation, initial);
|
|
652
|
-
return transitionValues((p) => {
|
|
653
|
-
const x = amount[0] * p;
|
|
654
|
-
const y = amount[1] * p;
|
|
655
|
-
const z = amount[2] * p;
|
|
656
|
-
vec3.add(this.rotation, vector3(x, y, z), this.rotation);
|
|
657
|
-
this.updated = true;
|
|
658
|
-
}, () => {
|
|
659
|
-
vec3.add(initial, amount, this.rotation);
|
|
660
|
-
}, t, f);
|
|
661
|
-
}
|
|
662
|
-
getRotation() {
|
|
663
|
-
return this.rotation;
|
|
664
|
-
}
|
|
665
|
-
getPos() {
|
|
666
|
-
return this.pos;
|
|
667
|
-
}
|
|
668
|
-
getAspectRatio() {
|
|
669
|
-
return this.aspectRatio;
|
|
670
|
-
}
|
|
671
|
-
}
|
|
672
597
|
const defaultShaderCode = `
|
|
673
598
|
struct Uniforms {
|
|
674
599
|
worldProjectionMatrix: mat4x4<f32>,
|
|
@@ -679,8 +604,7 @@ struct Uniforms {
|
|
|
679
604
|
|
|
680
605
|
@group(0) @binding(1) var<storage> instanceMatrices: array<mat4x4f>;
|
|
681
606
|
`;
|
|
682
|
-
export class ShaderGroup extends
|
|
683
|
-
geometry;
|
|
607
|
+
export class ShaderGroup extends EmptyElement {
|
|
684
608
|
code;
|
|
685
609
|
module;
|
|
686
610
|
pipeline;
|
|
@@ -703,8 +627,7 @@ export class ShaderGroup extends SceneCollection {
|
|
|
703
627
|
this.vertexParams = vertexParams;
|
|
704
628
|
this.valueBuffers = null;
|
|
705
629
|
}
|
|
706
|
-
|
|
707
|
-
super.propagateDevice(device);
|
|
630
|
+
onDeviceChange(device) {
|
|
708
631
|
this.module = device.createShaderModule({ code: this.code });
|
|
709
632
|
const presentationFormat = navigator.gpu.getPreferredCanvasFormat();
|
|
710
633
|
const bindGroupLayout = device.createBindGroupLayout(baseBindGroupLayout);
|
|
@@ -728,16 +651,16 @@ export class ShaderGroup extends SceneCollection {
|
|
|
728
651
|
getPipeline() {
|
|
729
652
|
return this.pipeline;
|
|
730
653
|
}
|
|
731
|
-
getBindGroupBuffers() {
|
|
654
|
+
getBindGroupBuffers(device) {
|
|
732
655
|
if (this.bindGroup === null)
|
|
733
656
|
return null;
|
|
734
|
-
if (
|
|
657
|
+
if (device === null)
|
|
735
658
|
return null;
|
|
736
659
|
const values = this.bindGroup.values();
|
|
737
660
|
if (this.valueBuffers === null) {
|
|
738
661
|
this.valueBuffers = [];
|
|
739
662
|
for (let i = 0; i < values.length; i++) {
|
|
740
|
-
const buffer = this.createBuffer(
|
|
663
|
+
const buffer = this.createBuffer(device, values[i]);
|
|
741
664
|
this.valueBuffers.push(buffer);
|
|
742
665
|
}
|
|
743
666
|
}
|
|
@@ -746,12 +669,12 @@ export class ShaderGroup extends SceneCollection {
|
|
|
746
669
|
const arrayConstructor = values[i].array;
|
|
747
670
|
const array = new arrayConstructor(values[i].value);
|
|
748
671
|
if (array.byteLength > this.valueBuffers[i].size) {
|
|
749
|
-
const newBuffer = this.createBuffer(
|
|
672
|
+
const newBuffer = this.createBuffer(device, values[i]);
|
|
750
673
|
this.valueBuffers[i].destroy();
|
|
751
674
|
this.valueBuffers[i] = newBuffer;
|
|
752
675
|
}
|
|
753
676
|
else {
|
|
754
|
-
|
|
677
|
+
device.queue.writeBuffer(this.valueBuffers[i], 0, array.buffer, array.byteOffset, array.byteLength);
|
|
755
678
|
}
|
|
756
679
|
}
|
|
757
680
|
}
|
|
@@ -770,9 +693,6 @@ export class ShaderGroup extends SceneCollection {
|
|
|
770
693
|
buffer.unmap();
|
|
771
694
|
return buffer;
|
|
772
695
|
}
|
|
773
|
-
updateMatrix(camera) {
|
|
774
|
-
this.defaultUpdateMatrix(camera);
|
|
775
|
-
}
|
|
776
696
|
getVertexParamGenerator() {
|
|
777
697
|
return this.paramGenerator;
|
|
778
698
|
}
|
|
@@ -780,39 +700,3 @@ export class ShaderGroup extends SceneCollection {
|
|
|
780
700
|
return !!this.bindGroup;
|
|
781
701
|
}
|
|
782
702
|
}
|
|
783
|
-
export class Group extends SceneCollection {
|
|
784
|
-
constructor(name) {
|
|
785
|
-
super(name);
|
|
786
|
-
}
|
|
787
|
-
move(amount, t, f) {
|
|
788
|
-
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
789
|
-
// @ts-ignore
|
|
790
|
-
return this.loopElements((el) => el.move(amount, t, f));
|
|
791
|
-
}
|
|
792
|
-
moveTo(pos, t, f) {
|
|
793
|
-
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
794
|
-
// @ts-ignore
|
|
795
|
-
return this.loopElements((el) => el.moveTo(pos, t, f));
|
|
796
|
-
}
|
|
797
|
-
rotate(amount, t, f) {
|
|
798
|
-
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
799
|
-
// @ts-ignore
|
|
800
|
-
return this.loopElements((el) => el.rotate(amount, t, f));
|
|
801
|
-
}
|
|
802
|
-
rotateTo(rotation, t, f) {
|
|
803
|
-
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
804
|
-
// @ts-ignore
|
|
805
|
-
return this.loopElements((el) => el.rotateTo(rotation, t, f));
|
|
806
|
-
}
|
|
807
|
-
fill(newColor, t, f) {
|
|
808
|
-
return this.loopElements((el) => el.fill(newColor, t, f));
|
|
809
|
-
}
|
|
810
|
-
loopElements(cb) {
|
|
811
|
-
const scene = this.getScene();
|
|
812
|
-
const promises = Array(scene.length);
|
|
813
|
-
for (let i = 0; i < scene.length; i++) {
|
|
814
|
-
promises[i] = cb(scene[i].getObj());
|
|
815
|
-
}
|
|
816
|
-
return wrapVoidPromise(Promise.all(promises));
|
|
817
|
-
}
|
|
818
|
-
}
|
package/dist/types.d.ts
CHANGED
|
@@ -65,6 +65,10 @@ export type LineGeometryParams = {
|
|
|
65
65
|
export type PolygonGeometryParams = {
|
|
66
66
|
points: Vertex[];
|
|
67
67
|
};
|
|
68
|
+
export type TraceLinesParams = {
|
|
69
|
+
vertices: Vertex[];
|
|
70
|
+
maxLength: number | null;
|
|
71
|
+
};
|
|
68
72
|
export type PipelineGroup = {
|
|
69
73
|
triangleList: GPURenderPipeline;
|
|
70
74
|
triangleStrip: GPURenderPipeline;
|
package/dist/utils.d.ts
CHANGED
|
@@ -21,9 +21,8 @@ export declare class Color {
|
|
|
21
21
|
export declare class Vertex {
|
|
22
22
|
private pos;
|
|
23
23
|
private color;
|
|
24
|
-
private is3d;
|
|
25
24
|
private uv;
|
|
26
|
-
constructor(x?: number, y?: number, z?: number, color?: Color,
|
|
25
|
+
constructor(x?: number, y?: number, z?: number, color?: Color, uv?: Vector2);
|
|
27
26
|
getPos(): Vector3;
|
|
28
27
|
setPos(pos: Vector3): void;
|
|
29
28
|
getColor(): Color | null;
|
|
@@ -33,18 +32,18 @@ export declare class Vertex {
|
|
|
33
32
|
setX(x: number): void;
|
|
34
33
|
setY(y: number): void;
|
|
35
34
|
setZ(z: number): void;
|
|
36
|
-
setIs3d(is3d: boolean): void;
|
|
37
35
|
clone(): Vertex;
|
|
38
36
|
toBuffer(defaultColor: Color): number[];
|
|
39
37
|
}
|
|
40
38
|
/**
|
|
41
|
-
* @param
|
|
42
|
-
* @param
|
|
39
|
+
* @param onFrame - called every frame until the animation is finished
|
|
40
|
+
* @param adjustment - called after animation is finished (called immediately when t = 0) if t > 0 it will only be called if `transformAdjustments` is enabled in settings
|
|
43
41
|
* @param t - animation time (seconds)
|
|
44
42
|
* @returns {Promise<void>}
|
|
45
43
|
*/
|
|
46
|
-
export declare function transitionValues(
|
|
47
|
-
|
|
44
|
+
export declare function transitionValues(onFrame: (deltaT: number, t: number, total: number) => void, adjustment: () => void, transitionLength: number, func?: (n: number) => number): Promise<void>;
|
|
45
|
+
type Shift<T extends any[]> = T extends [] ? [] : T extends [unknown, ...infer R] ? R : never;
|
|
46
|
+
export declare function frameLoop<T extends (dt: number, ...args: any[]) => any>(cb: T): (...params: Shift<Parameters<T>>) => void;
|
|
48
47
|
export declare function clamp(num: number, min: number, max: number): number;
|
|
49
48
|
export declare function lerp(a: number, b: number, t: number): number;
|
|
50
49
|
export declare function smoothStep(t: number): number;
|
|
@@ -68,7 +67,7 @@ export declare function vector2FromVector3(vec: Vector3): Vector2;
|
|
|
68
67
|
export declare function colorFromVector4(vec: Vector4): Color;
|
|
69
68
|
export declare function randomInt(range: number, min?: number): number;
|
|
70
69
|
export declare function randomColor(a?: number): Color;
|
|
71
|
-
export declare function vertex(x?: number, y?: number, z?: number, color?: Color,
|
|
70
|
+
export declare function vertex(x?: number, y?: number, z?: number, color?: Color, uv?: Vector2): Vertex;
|
|
72
71
|
export declare function color(r?: number, g?: number, b?: number, a?: number): Color;
|
|
73
72
|
export declare function colorf(val: number, a?: number): Color;
|
|
74
73
|
export declare function splinePoint2d(end: Vertex, control1: Vector2, control2: Vector2, detail?: number): SplinePoint2d;
|
|
@@ -82,3 +81,4 @@ export declare function distance3d(vector1: Vector3, vector2: Vector3): number;
|
|
|
82
81
|
export declare function toSceneObjInfo(el: AnySimulationElement, id?: string): SimSceneObjInfo;
|
|
83
82
|
export declare function toSceneObjInfoMany(el: AnySimulationElement[], id?: (string | undefined)[]): SimSceneObjInfo[];
|
|
84
83
|
export declare function interpolateColors(colors: Color[], t: number): Color;
|
|
84
|
+
export {};
|