simulationjsv2 0.6.0 → 0.7.2
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 +2 -0
- package/dist/constants.js +2 -0
- package/dist/geometry.d.ts +11 -1
- package/dist/geometry.js +31 -0
- package/dist/graphics.d.ts +60 -21
- package/dist/graphics.js +266 -109
- package/dist/internalUtils.d.ts +17 -10
- package/dist/internalUtils.js +51 -56
- package/dist/settings.d.ts +7 -0
- package/dist/settings.js +9 -0
- package/dist/simulation.d.ts +31 -72
- package/dist/simulation.js +150 -274
- 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, globalInfo } from './internalUtils.js';
|
|
7
|
+
import { Settings } from './settings.js';
|
|
7
8
|
const shader = `
|
|
8
9
|
struct Uniforms {
|
|
9
10
|
worldProjectionMatrix: mat4x4<f32>,
|
|
@@ -115,20 +116,107 @@ let aspectRatio = 0;
|
|
|
115
116
|
const projMat = matrix4();
|
|
116
117
|
const worldProjMat = matrix4();
|
|
117
118
|
const orthoMatrix = matrix4();
|
|
118
|
-
export class
|
|
119
|
+
export class Camera {
|
|
120
|
+
pos;
|
|
121
|
+
rotation;
|
|
122
|
+
aspectRatio = 1;
|
|
123
|
+
updated;
|
|
124
|
+
screenSize = vector2();
|
|
125
|
+
constructor(pos, rotation = vector3()) {
|
|
126
|
+
this.pos = pos;
|
|
127
|
+
this.updated = false;
|
|
128
|
+
this.rotation = rotation;
|
|
129
|
+
}
|
|
130
|
+
setScreenSize(size) {
|
|
131
|
+
this.screenSize = size;
|
|
132
|
+
this.aspectRatio = size[0] / size[1];
|
|
133
|
+
this.updated = true;
|
|
134
|
+
}
|
|
135
|
+
getScreenSize() {
|
|
136
|
+
return this.screenSize;
|
|
137
|
+
}
|
|
138
|
+
hasUpdated() {
|
|
139
|
+
return this.updated;
|
|
140
|
+
}
|
|
141
|
+
updateConsumed() {
|
|
142
|
+
this.updated = false;
|
|
143
|
+
}
|
|
144
|
+
move(amount, t = 0, f) {
|
|
145
|
+
const initial = vector3();
|
|
146
|
+
vec3.clone(this.pos, initial);
|
|
147
|
+
return transitionValues((p) => {
|
|
148
|
+
const x = amount[0] * p;
|
|
149
|
+
const y = amount[1] * p;
|
|
150
|
+
const z = amount[2] * p;
|
|
151
|
+
const diff = vector3(x, y, z);
|
|
152
|
+
vec3.add(this.pos, diff, this.pos);
|
|
153
|
+
}, () => {
|
|
154
|
+
vec3.add(initial, amount, this.pos);
|
|
155
|
+
}, t, f);
|
|
156
|
+
}
|
|
157
|
+
moveTo(pos, t = 0, f) {
|
|
158
|
+
const diff = vector3();
|
|
159
|
+
vec3.sub(pos, this.pos, diff);
|
|
160
|
+
return transitionValues((p) => {
|
|
161
|
+
const x = diff[0] * p;
|
|
162
|
+
const y = diff[1] * p;
|
|
163
|
+
const z = diff[2] * p;
|
|
164
|
+
const amount = vector3(x, y, z);
|
|
165
|
+
vec3.add(this.pos, amount, this.pos);
|
|
166
|
+
}, () => {
|
|
167
|
+
vec3.clone(pos, this.pos);
|
|
168
|
+
}, t, f);
|
|
169
|
+
}
|
|
170
|
+
rotateTo(value, t = 0, f) {
|
|
171
|
+
const diff = vec3.clone(value);
|
|
172
|
+
vec3.sub(diff, diff, this.rotation);
|
|
173
|
+
return transitionValues((p) => {
|
|
174
|
+
const x = diff[0] * p;
|
|
175
|
+
const y = diff[1] * p;
|
|
176
|
+
const z = diff[2] * p;
|
|
177
|
+
vec3.add(this.rotation, this.rotation, vector3(x, y, z));
|
|
178
|
+
this.updated = true;
|
|
179
|
+
}, () => {
|
|
180
|
+
this.rotation = value;
|
|
181
|
+
}, t, f);
|
|
182
|
+
}
|
|
183
|
+
rotate(amount, t = 0, f) {
|
|
184
|
+
const initial = vector3();
|
|
185
|
+
vec3.clone(this.rotation, initial);
|
|
186
|
+
return transitionValues((p) => {
|
|
187
|
+
const x = amount[0] * p;
|
|
188
|
+
const y = amount[1] * p;
|
|
189
|
+
const z = amount[2] * p;
|
|
190
|
+
vec3.add(this.rotation, vector3(x, y, z), this.rotation);
|
|
191
|
+
this.updated = true;
|
|
192
|
+
}, () => {
|
|
193
|
+
vec3.add(initial, amount, this.rotation);
|
|
194
|
+
}, t, f);
|
|
195
|
+
}
|
|
196
|
+
getRotation() {
|
|
197
|
+
return this.rotation;
|
|
198
|
+
}
|
|
199
|
+
getPos() {
|
|
200
|
+
return this.pos;
|
|
201
|
+
}
|
|
202
|
+
getAspectRatio() {
|
|
203
|
+
return this.aspectRatio;
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
export let camera = new Camera(vector3());
|
|
207
|
+
export class Simulation extends Settings {
|
|
119
208
|
canvasRef = null;
|
|
120
209
|
bgColor = new Color(255, 255, 255);
|
|
121
210
|
scene = [];
|
|
122
211
|
fittingElement = false;
|
|
123
212
|
running = true;
|
|
124
213
|
initialized = false;
|
|
125
|
-
frameRateView;
|
|
126
|
-
camera;
|
|
127
|
-
device = null;
|
|
128
214
|
pipelines = null;
|
|
129
215
|
renderInfo = null;
|
|
130
216
|
resizeEvents;
|
|
131
|
-
|
|
217
|
+
frameRateView;
|
|
218
|
+
constructor(idOrCanvasRef, sceneCamera = null, showFrameRate = false) {
|
|
219
|
+
super();
|
|
132
220
|
if (typeof idOrCanvasRef === 'string') {
|
|
133
221
|
const ref = document.getElementById(idOrCanvasRef);
|
|
134
222
|
if (ref !== null)
|
|
@@ -143,10 +231,9 @@ export class Simulation {
|
|
|
143
231
|
throw logger.error(`Canvas ref/id provided is invalid`);
|
|
144
232
|
}
|
|
145
233
|
const parent = this.canvasRef.parentElement;
|
|
146
|
-
if (
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
this.camera = camera;
|
|
234
|
+
if (sceneCamera) {
|
|
235
|
+
camera = sceneCamera;
|
|
236
|
+
}
|
|
150
237
|
if (parent === null)
|
|
151
238
|
throw logger.error('Canvas parent is null');
|
|
152
239
|
this.resizeEvents = [];
|
|
@@ -173,10 +260,21 @@ export class Simulation {
|
|
|
173
260
|
return (this.canvasRef?.height || 0) / devicePixelRatio;
|
|
174
261
|
}
|
|
175
262
|
add(el, id) {
|
|
176
|
-
|
|
263
|
+
if (el instanceof SimulationElement3d) {
|
|
264
|
+
const obj = new SimSceneObjInfo(el, id);
|
|
265
|
+
this.scene.unshift(obj);
|
|
266
|
+
}
|
|
267
|
+
else {
|
|
268
|
+
throw logger.error('Cannot add invalid SimulationElement');
|
|
269
|
+
}
|
|
177
270
|
}
|
|
178
271
|
remove(el) {
|
|
179
|
-
|
|
272
|
+
for (let i = 0; i < this.scene.length; i++) {
|
|
273
|
+
if (this.scene[i].getObj() === el) {
|
|
274
|
+
this.scene.splice(i, 1);
|
|
275
|
+
break;
|
|
276
|
+
}
|
|
277
|
+
}
|
|
180
278
|
}
|
|
181
279
|
removeId(id) {
|
|
182
280
|
removeObjectId(this.scene, id);
|
|
@@ -221,25 +319,16 @@ export class Simulation {
|
|
|
221
319
|
if (!ctx)
|
|
222
320
|
throw logger.error('Context is null');
|
|
223
321
|
const device = await adapter.requestDevice();
|
|
224
|
-
|
|
225
|
-
this.propagateDevice(device);
|
|
322
|
+
globalInfo.setDevice(device);
|
|
226
323
|
ctx.configure({
|
|
227
324
|
device,
|
|
228
325
|
format: 'bgra8unorm'
|
|
229
326
|
});
|
|
230
327
|
const screenSize = vector2(this.canvasRef.width, this.canvasRef.height);
|
|
231
|
-
|
|
328
|
+
camera.setScreenSize(screenSize);
|
|
232
329
|
this.render(ctx);
|
|
233
330
|
})();
|
|
234
331
|
}
|
|
235
|
-
propagateDevice(device) {
|
|
236
|
-
for (let i = 0; i < this.scene.length; i++) {
|
|
237
|
-
const el = this.scene[i].getObj();
|
|
238
|
-
if (el instanceof SceneCollection) {
|
|
239
|
-
el.setDevice(device);
|
|
240
|
-
}
|
|
241
|
-
}
|
|
242
|
-
}
|
|
243
332
|
stop() {
|
|
244
333
|
this.running = false;
|
|
245
334
|
}
|
|
@@ -253,10 +342,10 @@ export class Simulation {
|
|
|
253
342
|
return this.scene.map((item) => item.getObj());
|
|
254
343
|
}
|
|
255
344
|
render(ctx) {
|
|
256
|
-
|
|
345
|
+
const device = globalInfo.getDevice();
|
|
346
|
+
if (this.canvasRef === null || device === null)
|
|
257
347
|
return;
|
|
258
348
|
const canvas = this.canvasRef;
|
|
259
|
-
const device = this.device;
|
|
260
349
|
canvas.width = canvas.clientWidth * devicePixelRatio;
|
|
261
350
|
canvas.height = canvas.clientHeight * devicePixelRatio;
|
|
262
351
|
const presentationFormat = navigator.gpu.getPreferredCanvasFormat();
|
|
@@ -294,8 +383,8 @@ export class Simulation {
|
|
|
294
383
|
updateProjectionMatrix(projMat, newAspectRatio);
|
|
295
384
|
aspectRatio = newAspectRatio;
|
|
296
385
|
}
|
|
297
|
-
updateWorldProjectionMatrix(worldProjMat, projMat
|
|
298
|
-
updateOrthoProjectionMatrix(orthoMatrix,
|
|
386
|
+
updateWorldProjectionMatrix(worldProjMat, projMat);
|
|
387
|
+
updateOrthoProjectionMatrix(orthoMatrix, camera.getScreenSize());
|
|
299
388
|
let multisampleTexture = buildMultisampleTexture(device, ctx, canvas.width, canvas.height);
|
|
300
389
|
let depthTexture = buildDepthTexture(device, canvas.width, canvas.height);
|
|
301
390
|
const renderPassDescriptor = {
|
|
@@ -328,14 +417,14 @@ export class Simulation {
|
|
|
328
417
|
prevFps = fps;
|
|
329
418
|
canvas.width = canvas.clientWidth * devicePixelRatio;
|
|
330
419
|
canvas.height = canvas.clientHeight * devicePixelRatio;
|
|
331
|
-
const screenSize =
|
|
420
|
+
const screenSize = camera.getScreenSize();
|
|
332
421
|
if (screenSize[0] !== canvas.width || screenSize[1] !== canvas.height) {
|
|
333
|
-
|
|
422
|
+
camera.setScreenSize(vector2(canvas.width, canvas.height));
|
|
334
423
|
screenSize[0] = canvas.width;
|
|
335
424
|
screenSize[1] = canvas.height;
|
|
336
|
-
aspectRatio =
|
|
425
|
+
aspectRatio = camera.getAspectRatio();
|
|
337
426
|
updateProjectionMatrix(projMat, aspectRatio);
|
|
338
|
-
updateWorldProjectionMatrix(worldProjMat, projMat
|
|
427
|
+
updateWorldProjectionMatrix(worldProjMat, projMat);
|
|
339
428
|
multisampleTexture = buildMultisampleTexture(device, ctx, screenSize[0], screenSize[1]);
|
|
340
429
|
depthTexture = buildDepthTexture(device, screenSize[0], screenSize[1]);
|
|
341
430
|
renderPassDescriptor.depthStencilAttachment.view = depthTexture.createView();
|
|
@@ -346,9 +435,9 @@ export class Simulation {
|
|
|
346
435
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
347
436
|
// @ts-ignore
|
|
348
437
|
renderPassDescriptor.colorAttachments[0].resolveTarget = ctx.getCurrentTexture().createView();
|
|
349
|
-
if (
|
|
350
|
-
updateOrthoProjectionMatrix(orthoMatrix,
|
|
351
|
-
updateWorldProjectionMatrix(worldProjMat, projMat
|
|
438
|
+
if (camera.hasUpdated()) {
|
|
439
|
+
updateOrthoProjectionMatrix(orthoMatrix, camera.getScreenSize());
|
|
440
|
+
updateWorldProjectionMatrix(worldProjMat, projMat);
|
|
352
441
|
}
|
|
353
442
|
const commandEncoder = device.createCommandEncoder();
|
|
354
443
|
const passEncoder = commandEncoder.beginRenderPass(renderPassDescriptor);
|
|
@@ -362,7 +451,7 @@ export class Simulation {
|
|
|
362
451
|
});
|
|
363
452
|
}
|
|
364
453
|
this.renderScene(device, passEncoder, this.renderInfo.vertexBuffer, this.scene, 0, diff);
|
|
365
|
-
|
|
454
|
+
camera.updateConsumed();
|
|
366
455
|
passEncoder.end();
|
|
367
456
|
device.queue.submit([commandEncoder.finish()]);
|
|
368
457
|
};
|
|
@@ -384,7 +473,7 @@ export class Simulation {
|
|
|
384
473
|
scene[i].traverseLife(diff);
|
|
385
474
|
}
|
|
386
475
|
const obj = scene[i].getObj();
|
|
387
|
-
if (obj
|
|
476
|
+
if (obj.hasChildren()) {
|
|
388
477
|
let shaderInfo = undefined;
|
|
389
478
|
if (obj instanceof ShaderGroup) {
|
|
390
479
|
const pipeline = obj.getPipeline();
|
|
@@ -394,30 +483,27 @@ export class Simulation {
|
|
|
394
483
|
paramGenerator: obj.getVertexParamGenerator(),
|
|
395
484
|
bufferInfo: obj.hasBindGroup()
|
|
396
485
|
? {
|
|
397
|
-
buffers: obj.getBindGroupBuffers(),
|
|
486
|
+
buffers: obj.getBindGroupBuffers(device),
|
|
398
487
|
layout: obj.getBindGroupLayout()
|
|
399
488
|
}
|
|
400
489
|
: null
|
|
401
490
|
};
|
|
402
491
|
}
|
|
403
492
|
}
|
|
404
|
-
currentOffset += this.renderScene(device, passEncoder, vertexBuffer, obj.
|
|
405
|
-
continue;
|
|
493
|
+
currentOffset += this.renderScene(device, passEncoder, vertexBuffer, obj.getChildrenInfos(), currentOffset, diff, shaderInfo);
|
|
406
494
|
}
|
|
495
|
+
if (obj.isEmpty)
|
|
496
|
+
continue;
|
|
407
497
|
const buffer = new Float32Array(obj.getBuffer(shaderInfo?.paramGenerator));
|
|
408
498
|
const bufLen = shaderInfo?.paramGenerator?.bufferSize || BUF_LEN;
|
|
409
499
|
const vertexCount = buffer.length / bufLen;
|
|
410
|
-
device.queue.writeBuffer(vertexBuffer, currentOffset, buffer);
|
|
500
|
+
device.queue.writeBuffer(vertexBuffer, currentOffset, buffer.buffer, buffer.byteOffset, buffer.byteLength);
|
|
411
501
|
vertexBuffer.unmap();
|
|
412
502
|
passEncoder.setVertexBuffer(0, vertexBuffer, currentOffset, buffer.byteLength);
|
|
413
|
-
const modelMatrix = obj.getModelMatrix(
|
|
414
|
-
const uniformBuffer = obj.getUniformBuffer(
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
}
|
|
418
|
-
else {
|
|
419
|
-
device.queue.writeBuffer(uniformBuffer, worldProjMatOffset, orthoMatrix.buffer, orthoMatrix.byteOffset, orthoMatrix.byteLength);
|
|
420
|
-
}
|
|
503
|
+
const modelMatrix = obj.getModelMatrix();
|
|
504
|
+
const uniformBuffer = obj.getUniformBuffer(modelMatrix);
|
|
505
|
+
const projBuf = obj.is3d ? worldProjMat : orthoMatrix;
|
|
506
|
+
device.queue.writeBuffer(uniformBuffer, worldProjMatOffset, projBuf.buffer, projBuf.byteOffset, projBuf.byteLength);
|
|
421
507
|
if (shaderInfo) {
|
|
422
508
|
passEncoder.setPipeline(shaderInfo.pipeline);
|
|
423
509
|
}
|
|
@@ -436,9 +522,10 @@ export class Simulation {
|
|
|
436
522
|
let instances = 1;
|
|
437
523
|
if (this.renderInfo) {
|
|
438
524
|
let instanceBuffer;
|
|
439
|
-
if (obj
|
|
525
|
+
if (obj.isInstance) {
|
|
440
526
|
instances = obj.getNumInstances();
|
|
441
|
-
instanceBuffer =
|
|
527
|
+
instanceBuffer =
|
|
528
|
+
obj.getMatrixBuffer() ?? this.renderInfo.instanceBuffer;
|
|
442
529
|
}
|
|
443
530
|
else {
|
|
444
531
|
instanceBuffer = this.renderInfo.instanceBuffer;
|
|
@@ -480,7 +567,7 @@ export class Simulation {
|
|
|
480
567
|
currentOffset += buffer.byteLength;
|
|
481
568
|
}
|
|
482
569
|
for (let i = toRemove.length - 1; i >= 0; i--) {
|
|
483
|
-
|
|
570
|
+
this.remove(scene[i].getObj());
|
|
484
571
|
}
|
|
485
572
|
return currentOffset - startOffset;
|
|
486
573
|
}
|
|
@@ -496,179 +583,6 @@ export class Simulation {
|
|
|
496
583
|
}
|
|
497
584
|
}
|
|
498
585
|
}
|
|
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
586
|
const defaultShaderCode = `
|
|
673
587
|
struct Uniforms {
|
|
674
588
|
worldProjectionMatrix: mat4x4<f32>,
|
|
@@ -679,8 +593,7 @@ struct Uniforms {
|
|
|
679
593
|
|
|
680
594
|
@group(0) @binding(1) var<storage> instanceMatrices: array<mat4x4f>;
|
|
681
595
|
`;
|
|
682
|
-
export class ShaderGroup extends
|
|
683
|
-
geometry;
|
|
596
|
+
export class ShaderGroup extends EmptyElement {
|
|
684
597
|
code;
|
|
685
598
|
module;
|
|
686
599
|
pipeline;
|
|
@@ -703,8 +616,8 @@ export class ShaderGroup extends SceneCollection {
|
|
|
703
616
|
this.vertexParams = vertexParams;
|
|
704
617
|
this.valueBuffers = null;
|
|
705
618
|
}
|
|
706
|
-
|
|
707
|
-
|
|
619
|
+
initPipeline() {
|
|
620
|
+
const device = globalInfo.errorGetDevice();
|
|
708
621
|
this.module = device.createShaderModule({ code: this.code });
|
|
709
622
|
const presentationFormat = navigator.gpu.getPreferredCanvasFormat();
|
|
710
623
|
const bindGroupLayout = device.createBindGroupLayout(baseBindGroupLayout);
|
|
@@ -726,18 +639,20 @@ export class ShaderGroup extends SceneCollection {
|
|
|
726
639
|
return this.bindGroupLayout;
|
|
727
640
|
}
|
|
728
641
|
getPipeline() {
|
|
642
|
+
if (!this.pipeline)
|
|
643
|
+
this.initPipeline();
|
|
729
644
|
return this.pipeline;
|
|
730
645
|
}
|
|
731
|
-
getBindGroupBuffers() {
|
|
646
|
+
getBindGroupBuffers(device) {
|
|
732
647
|
if (this.bindGroup === null)
|
|
733
648
|
return null;
|
|
734
|
-
if (
|
|
649
|
+
if (device === null)
|
|
735
650
|
return null;
|
|
736
651
|
const values = this.bindGroup.values();
|
|
737
652
|
if (this.valueBuffers === null) {
|
|
738
653
|
this.valueBuffers = [];
|
|
739
654
|
for (let i = 0; i < values.length; i++) {
|
|
740
|
-
const buffer = this.createBuffer(
|
|
655
|
+
const buffer = this.createBuffer(device, values[i]);
|
|
741
656
|
this.valueBuffers.push(buffer);
|
|
742
657
|
}
|
|
743
658
|
}
|
|
@@ -746,12 +661,12 @@ export class ShaderGroup extends SceneCollection {
|
|
|
746
661
|
const arrayConstructor = values[i].array;
|
|
747
662
|
const array = new arrayConstructor(values[i].value);
|
|
748
663
|
if (array.byteLength > this.valueBuffers[i].size) {
|
|
749
|
-
const newBuffer = this.createBuffer(
|
|
664
|
+
const newBuffer = this.createBuffer(device, values[i]);
|
|
750
665
|
this.valueBuffers[i].destroy();
|
|
751
666
|
this.valueBuffers[i] = newBuffer;
|
|
752
667
|
}
|
|
753
668
|
else {
|
|
754
|
-
|
|
669
|
+
device.queue.writeBuffer(this.valueBuffers[i], 0, array.buffer, array.byteOffset, array.byteLength);
|
|
755
670
|
}
|
|
756
671
|
}
|
|
757
672
|
}
|
|
@@ -770,9 +685,6 @@ export class ShaderGroup extends SceneCollection {
|
|
|
770
685
|
buffer.unmap();
|
|
771
686
|
return buffer;
|
|
772
687
|
}
|
|
773
|
-
updateMatrix(camera) {
|
|
774
|
-
this.defaultUpdateMatrix(camera);
|
|
775
|
-
}
|
|
776
688
|
getVertexParamGenerator() {
|
|
777
689
|
return this.paramGenerator;
|
|
778
690
|
}
|
|
@@ -780,39 +692,3 @@ export class ShaderGroup extends SceneCollection {
|
|
|
780
692
|
return !!this.bindGroup;
|
|
781
693
|
}
|
|
782
694
|
}
|
|
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 {};
|