pacem 0.60.3-mercator → 0.60.3-navier

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.
Files changed (57) hide show
  1. package/dist/css/pacem-dark-content.min.css +1 -1
  2. package/dist/css/pacem-dark-shell.min.css +1 -1
  3. package/dist/css/pacem-dark.min.css +1 -1
  4. package/dist/css/pacem-light-content.min.css +1 -1
  5. package/dist/css/pacem-light-shell.min.css +1 -1
  6. package/dist/css/pacem-light.min.css +1 -1
  7. package/dist/css/pacem-phousys-content.min.css +1 -1
  8. package/dist/css/pacem-phousys-shell.min.css +1 -1
  9. package/dist/css/pacem-phousys.min.css +1 -1
  10. package/dist/js/azure-maps.d.ts +1 -1
  11. package/dist/js/pacem-2d.d.ts +1 -1
  12. package/dist/js/pacem-2d.js +1 -1
  13. package/dist/js/pacem-2d.min.js +1 -1
  14. package/dist/js/pacem-3d.d.ts +6 -3
  15. package/dist/js/pacem-3d.js +105 -25
  16. package/dist/js/pacem-3d.min.js +2 -2
  17. package/dist/js/pacem-charts.d.ts +1 -1
  18. package/dist/js/pacem-charts.js +1 -1
  19. package/dist/js/pacem-charts.min.js +1 -1
  20. package/dist/js/pacem-cms.d.ts +1 -1
  21. package/dist/js/pacem-cms.js +1 -1
  22. package/dist/js/pacem-cms.min.js +1 -1
  23. package/dist/js/pacem-core.d.ts +1 -1
  24. package/dist/js/pacem-core.js +6 -4
  25. package/dist/js/pacem-core.min.js +2 -2
  26. package/dist/js/pacem-foundation.d.ts +1 -1
  27. package/dist/js/pacem-foundation.js +1 -1
  28. package/dist/js/pacem-foundation.min.js +1 -1
  29. package/dist/js/pacem-fx.d.ts +1 -1
  30. package/dist/js/pacem-fx.js +1 -1
  31. package/dist/js/pacem-fx.min.js +1 -1
  32. package/dist/js/pacem-logging.d.ts +1 -1
  33. package/dist/js/pacem-logging.js +1 -1
  34. package/dist/js/pacem-logging.min.js +1 -1
  35. package/dist/js/pacem-maps.d.ts +1 -1
  36. package/dist/js/pacem-maps.js +1 -1
  37. package/dist/js/pacem-maps.min.js +1 -1
  38. package/dist/js/pacem-media.d.ts +1 -1
  39. package/dist/js/pacem-media.js +1 -1
  40. package/dist/js/pacem-media.min.js +1 -1
  41. package/dist/js/pacem-networking.d.ts +1 -1
  42. package/dist/js/pacem-networking.js +1 -1
  43. package/dist/js/pacem-networking.min.js +1 -1
  44. package/dist/js/pacem-numerical.d.ts +1 -1
  45. package/dist/js/pacem-numerical.js +1 -1
  46. package/dist/js/pacem-numerical.min.js +1 -1
  47. package/dist/js/pacem-plus.d.ts +1 -1
  48. package/dist/js/pacem-plus.js +1 -1
  49. package/dist/js/pacem-plus.min.js +1 -1
  50. package/dist/js/pacem-scaffolding.d.ts +1 -1
  51. package/dist/js/pacem-scaffolding.js +1 -1
  52. package/dist/js/pacem-scaffolding.min.js +1 -1
  53. package/dist/js/pacem-ui.d.ts +1 -1
  54. package/dist/js/pacem-ui.js +1 -1
  55. package/dist/js/pacem-ui.min.js +1 -1
  56. package/dist/js/swagger-types.d.ts +1 -1
  57. package/package.json +1 -1
@@ -1,5 +1,5 @@
1
1
  /**
2
- * pacem v0.60.3-mercator (https://js.pacem.it)
2
+ * pacem v0.60.3-navier (https://js.pacem.it)
3
3
  * Copyright 2026 Pacem (https://pacem.it)
4
4
  * Licensed under Apache-2.0
5
5
  */
@@ -1,5 +1,5 @@
1
1
  /**
2
- * pacem v0.60.3-mercator (https://js.pacem.it)
2
+ * pacem v0.60.3-navier (https://js.pacem.it)
3
3
  * Copyright 2026 Pacem (https://pacem.it)
4
4
  * Licensed under Apache-2.0
5
5
  */
@@ -1,5 +1,5 @@
1
1
  /**
2
- * pacem v0.60.3-mercator (https://js.pacem.it)
2
+ * pacem v0.60.3-navier (https://js.pacem.it)
3
3
  * Copyright 2026 Pacem (https://pacem.it)
4
4
  * Licensed under Apache-2.0
5
5
  */
@@ -1,5 +1,5 @@
1
1
  /**
2
- * pacem v0.60.3-mercator (https://js.pacem.it)
2
+ * pacem v0.60.3-navier (https://js.pacem.it)
3
3
  * Copyright 2026 Pacem (https://pacem.it)
4
4
  * Licensed under Apache-2.0
5
5
  */
@@ -1,5 +1,5 @@
1
1
  /**
2
- * pacem v0.60.3-mercator (https://js.pacem.it)
2
+ * pacem v0.60.3-navier (https://js.pacem.it)
3
3
  * Copyright 2026 Pacem (https://pacem.it)
4
4
  * Licensed under Apache-2.0
5
5
  */
@@ -1,5 +1,5 @@
1
1
  /**
2
- * pacem v0.60.3-mercator (https://js.pacem.it)
2
+ * pacem v0.60.3-navier (https://js.pacem.it)
3
3
  * Copyright 2026 Pacem (https://pacem.it)
4
4
  * Licensed under Apache-2.0
5
5
  */
@@ -1,5 +1,5 @@
1
1
  /**
2
- * pacem v0.60.3-mercator (https://js.pacem.it)
2
+ * pacem v0.60.3-navier (https://js.pacem.it)
3
3
  * Copyright 2026 Pacem (https://pacem.it)
4
4
  * Licensed under Apache-2.0
5
5
  */
@@ -1,5 +1,5 @@
1
1
  /**
2
- * pacem v0.60.3-mercator (https://js.pacem.it)
2
+ * pacem v0.60.3-navier (https://js.pacem.it)
3
3
  * Copyright 2026 Pacem (https://pacem.it)
4
4
  * Licensed under Apache-2.0
5
5
  */
@@ -1,5 +1,5 @@
1
1
  /**
2
- * pacem v0.60.3-mercator (https://js.pacem.it)
2
+ * pacem v0.60.3-navier (https://js.pacem.it)
3
3
  * Copyright 2026 Pacem (https://pacem.it)
4
4
  * Licensed under Apache-2.0
5
5
  */
@@ -1,5 +1,5 @@
1
1
  /**
2
- * pacem v0.60.3-mercator (https://js.pacem.it)
2
+ * pacem v0.60.3-navier (https://js.pacem.it)
3
3
  * Copyright 2026 Pacem (https://pacem.it)
4
4
  * Licensed under Apache-2.0
5
5
  */
@@ -1,5 +1,5 @@
1
1
  /**
2
- * pacem v0.60.3-mercator (https://js.pacem.it)
2
+ * pacem v0.60.3-navier (https://js.pacem.it)
3
3
  * Copyright 2026 Pacem (https://pacem.it)
4
4
  * Licensed under Apache-2.0
5
5
  */
@@ -1,5 +1,5 @@
1
1
  /**
2
- * pacem v0.60.3-mercator (https://js.pacem.it)
2
+ * pacem v0.60.3-navier (https://js.pacem.it)
3
3
  * Copyright 2026 Pacem (https://pacem.it)
4
4
  * Licensed under Apache-2.0
5
5
  */
@@ -1,5 +1,5 @@
1
1
  /**
2
- * pacem v0.60.3-mercator (https://js.pacem.it)
2
+ * pacem v0.60.3-navier (https://js.pacem.it)
3
3
  * Copyright 2026 Pacem (https://pacem.it)
4
4
  * Licensed under Apache-2.0
5
5
  */
@@ -1,5 +1,5 @@
1
1
  /**
2
- * pacem v0.60.3-mercator (https://js.pacem.it)
2
+ * pacem v0.60.3-navier (https://js.pacem.it)
3
3
  * Copyright 2026 Pacem (https://pacem.it)
4
4
  * Licensed under Apache-2.0
5
5
  */
@@ -564,13 +564,16 @@ declare namespace Pacem.Drawing3D.WebGPU {
564
564
  version: number;
565
565
  };
566
566
  type RenderableBufferSet = Record<'meshes' | 'cameras' | 'lights' | 'groups', RenderableBuffer[]>;
567
+ type PipelineContext = Context & {
568
+ pipeline: RenderPipeline;
569
+ };
567
570
  interface ManagedBuffer<T> {
568
571
  readonly item: T;
569
- buffer(context: Context, key: RenderableBufferKey): Buffer & {
572
+ buffer(context: PipelineContext, key: RenderableBufferKey): Buffer & {
570
573
  fresh: boolean;
571
574
  };
572
575
  version?: (key: RenderableBufferKey) => number;
573
- texture(context: Context, key?: MaterialKey): Texture & {
576
+ texture(context: PipelineContext, key?: MaterialKey): Texture & {
574
577
  fresh: boolean;
575
578
  };
576
579
  lock(): void;
@@ -1,5 +1,5 @@
1
1
  /**
2
- * pacem v0.60.3-mercator (https://js.pacem.it)
2
+ * pacem v0.60.3-navier (https://js.pacem.it)
3
3
  * Copyright 2026 Pacem (https://pacem.it)
4
4
  * Licensed under Apache-2.0
5
5
  */
@@ -3301,7 +3301,7 @@ var Pacem;
3301
3301
  build(pipelineOptions) {
3302
3302
  const options = Pacem.Utils.extend({}, DefaultPipelineOptions, pipelineOptions ?? {});
3303
3303
  const builder = this._builder, wgsl = builder.build(options.modifiers);
3304
- const ctx = this._context;
3304
+ const ctx = Pacem.Utils.extend({ pipeline: this }, this._context);
3305
3305
  const device = ctx.device;
3306
3306
  // #region VERTEX
3307
3307
  // build vertex state
@@ -3539,7 +3539,7 @@ var Pacem;
3539
3539
  const bindGroup = this._ensureCameraProjectionAndInteractionDataBindGroup(cameraBuffer.item, viewTransformBufferBuffer, interactionDataBufferBuffer,
3540
3540
  // since fresh could mean also "camera switched" (e.g. from ortho to perspective and then back to ortho) there's risk
3541
3541
  // to target destroyed buffers, this refresh the bind group if either buffer is fresh.
3542
- // POssibilities for fine-tuning in future.
3542
+ // Possibilities for fine-tuning in future.
3543
3543
  viewTransformBuffer.fresh || interactionDataBuffer.fresh, group, raycasting);
3544
3544
  pass.setBindGroup(group, bindGroup);
3545
3545
  };
@@ -3575,7 +3575,8 @@ var Pacem;
3575
3575
  if (hasLighting) {
3576
3576
  const lightArray = Array.from(buffers);
3577
3577
  const lightBuffers = lightArray.map(l => { return { buffer: l.buffer(ctx, 'light'), id: l.item.key }; });
3578
- const bindGroup = this._ensureLightingBindGroup(lightBuffers, lightArray.some(i => i.item.flags.length > 0), lightingGroupIndex);
3578
+ const refresh = lightBuffers.some(b => b.buffer.fresh);
3579
+ const bindGroup = this._ensureLightingBindGroup(lightBuffers, refresh, lightingGroupIndex);
3579
3580
  for (let lightBuffer of lightBuffers) {
3580
3581
  // writes only if buffer is fresh
3581
3582
  PipelineUtils.writeBufferConditionally(device, lightBuffer.buffer);
@@ -3593,7 +3594,8 @@ var Pacem;
3593
3594
  // writes only if buffer is fresh
3594
3595
  PipelineUtils.writeBufferConditionally(device, u32id);
3595
3596
  const group = WebGPU.UNIFORM_GROUP_INDEX_COLORPICKING;
3596
- const bindGroup = this._ensureU32idBindGroup(meshBuffer.item, u32idBuffer, false /* reuse u32id.fresh*/);
3597
+ const refresh = u32id.fresh;
3598
+ const bindGroup = this._ensureU32idBindGroup(meshBuffer.item, u32idBuffer, refresh /* reuse u32id.fresh*/);
3597
3599
  pass.setBindGroup(group, bindGroup);
3598
3600
  };
3599
3601
  }
@@ -3807,7 +3809,7 @@ var Pacem;
3807
3809
  build(pipelineOptions) {
3808
3810
  const options = Pacem.Utils.extend({}, DefaultPipelineOptions, pipelineOptions ?? {});
3809
3811
  const builder = this._lineBuilder, wgsl = builder.build();
3810
- const ctx = this.context;
3812
+ const ctx = Pacem.Utils.extend({ pipeline: this }, this.#context);
3811
3813
  const device = ctx.device;
3812
3814
  // TODO: switch topology based on this flag
3813
3815
  const fatLines = wgsl.metadata.thickness > 1;
@@ -4438,7 +4440,7 @@ var Pacem;
4438
4440
  }
4439
4441
  #u32id;
4440
4442
  #parent;
4441
- #u32idBuffer;
4443
+ #u32idBuffer = new Map();
4442
4444
  get parent() {
4443
4445
  return this.#parent;
4444
4446
  }
@@ -4473,12 +4475,15 @@ var Pacem;
4473
4475
  buffer(context, key) {
4474
4476
  if (key === 'u32id') {
4475
4477
  const u32idBuffer = this.#u32idBuffer;
4476
- if (!Pacem.Utils.isNull(u32idBuffer)) {
4477
- return Pacem.Utils.extend({ fresh: false }, u32idBuffer);
4478
+ const { pipeline, device } = context;
4479
+ if (u32idBuffer.has(pipeline)) {
4480
+ return Pacem.Utils.extend({ fresh: false }, u32idBuffer.get(pipeline));
4478
4481
  }
4479
4482
  const u32idBufferValue = new Uint32Array([this.id]);
4480
- const u32idBufferBuffer = WebGPU.Buffers.createUniform(context.device, u32idBufferValue, WebGPU.LABEL_PREFIX + 'u32id-buffer');
4481
- return Pacem.Utils.extend(this.#u32idBuffer = { buffer: u32idBufferBuffer, value: u32idBufferValue, version: performance.now() }, { fresh: true });
4483
+ const u32idBufferBuffer = WebGPU.Buffers.createUniform(device, u32idBufferValue, WebGPU.LABEL_PREFIX + 'u32id-buffer');
4484
+ const retval = Pacem.Utils.extend({ buffer: u32idBufferBuffer, value: u32idBufferValue, version: performance.now() }, { fresh: true });
4485
+ this.#u32idBuffer.set(pipeline, retval);
4486
+ return retval;
4482
4487
  }
4483
4488
  const retval = this.specificBuffer(context, key);
4484
4489
  this.#versions.set(key, retval.version);
@@ -4513,6 +4518,7 @@ var Pacem;
4513
4518
  // #endregion
4514
4519
  // #region CAMERA
4515
4520
  class RenderableCameraBuffer extends RenderableBufferBase {
4521
+ #viewBag = new Map();
4516
4522
  #view;
4517
4523
  constructor(camera) {
4518
4524
  super(camera);
@@ -4522,10 +4528,17 @@ var Pacem;
4522
4528
  }
4523
4529
  specificBuffer(context, key) {
4524
4530
  //const camera = this.item;
4525
- const fresh = Pacem.Utils.isNull(this.#view) || this.allFlags().length > 0;
4526
- if (fresh) {
4531
+ let fresh = false;
4532
+ if (this.allFlags().length > 0 || Pacem.Utils.isNull(this.#view)) {
4533
+ fresh = true;
4534
+ this.#viewBag.clear();
4527
4535
  this._rebuildMatrices(context);
4528
4536
  }
4537
+ const { pipeline } = context;
4538
+ if (!this.#viewBag.has(pipeline)) {
4539
+ fresh = true;
4540
+ this.#viewBag.set(pipeline, this.#view);
4541
+ }
4529
4542
  RenderableBuffer.clearFlags(this);
4530
4543
  switch (key) {
4531
4544
  case 'cameraViewTransform':
@@ -4557,6 +4570,7 @@ var Pacem;
4557
4570
  }
4558
4571
  }
4559
4572
  _destroyView() {
4573
+ this.#viewBag.clear();
4560
4574
  const view = this.#view;
4561
4575
  this.#view = null;
4562
4576
  this.destroySafely(view);
@@ -4568,6 +4582,7 @@ var Pacem;
4568
4582
  // #endregion
4569
4583
  // #region GEOMETRY
4570
4584
  class GeometryBuffer extends ManagedBufferBase {
4585
+ #bufferBag = {};
4571
4586
  #freshness = { positions: true, normals: true, uv: true, packed: true };
4572
4587
  #geometryBuffers;
4573
4588
  constructor(geometry) {
@@ -4578,28 +4593,38 @@ var Pacem;
4578
4593
  const flags = this.item.flags ?? [];
4579
4594
  if (Pacem.Utils.isNull(this.#geometryBuffers) || flags.includes(Drawing3D.StalePropertyFlag.Geometry)) {
4580
4595
  flags.splice(0);
4596
+ this.#bufferBag = /* reset */ {};
4581
4597
  this._rebuildGeometryBuffers(context);
4582
4598
  }
4583
4599
  const freshness = this.#freshness;
4584
4600
  const geom = this.#geometryBuffers;
4601
+ const { pipeline } = context;
4602
+ const bag = (this.#bufferBag[key] ??= new Map());
4603
+ const newInPipeline = !bag.has(pipeline);
4604
+ const ensureInBag = (buffer) => {
4605
+ if (newInPipeline) {
4606
+ bag.set(pipeline, buffer);
4607
+ }
4608
+ return buffer;
4609
+ };
4585
4610
  switch (key) {
4586
4611
  case 'geometryPositions':
4587
4612
  const { positions } = geom, posFresh = freshness.positions;
4588
4613
  freshness.positions = false;
4589
- return Pacem.Utils.extend(positions, { fresh: posFresh });
4614
+ return Pacem.Utils.extend(ensureInBag(positions), { fresh: posFresh || newInPipeline });
4590
4615
  case 'geometryNormals':
4591
4616
  const { normals } = geom, normFresh = freshness.normals;
4592
4617
  freshness.normals = false;
4593
- return Pacem.Utils.extend(normals, { fresh: normFresh });
4618
+ return Pacem.Utils.extend(ensureInBag(normals), { fresh: normFresh || newInPipeline });
4594
4619
  case 'geometryTexCoords':
4595
4620
  const { uv } = geom, uvFresh = freshness.uv;
4596
4621
  freshness.uv = false;
4597
- return Pacem.Utils.extend({ fresh: uvFresh }, uv);
4622
+ return Pacem.Utils.extend({ fresh: uvFresh || newInPipeline }, ensureInBag(uv));
4598
4623
  case 'geometry':
4599
4624
  // alltogether
4600
4625
  const { packed } = geom, geomFresh = freshness.packed;
4601
4626
  freshness.packed = false;
4602
- return Pacem.Utils.extend(packed, { fresh: geomFresh });
4627
+ return Pacem.Utils.extend(ensureInBag(packed), { fresh: geomFresh || newInPipeline });
4603
4628
  default:
4604
4629
  throwBufferRequestError(key, GeometryBuffer);
4605
4630
  }
@@ -4657,6 +4682,7 @@ var Pacem;
4657
4682
  }
4658
4683
  }
4659
4684
  _destroyBuffers() {
4685
+ this.#bufferBag = {};
4660
4686
  const obsolete = this.#geometryBuffers;
4661
4687
  if (!Pacem.Utils.isNull(obsolete)) {
4662
4688
  this.destroySafely(obsolete.positions, obsolete.normals, obsolete.uv);
@@ -4669,6 +4695,8 @@ var Pacem;
4669
4695
  // #endregion
4670
4696
  // #region MATERIAL
4671
4697
  class MaterialBuffer extends ManagedBufferBase {
4698
+ #bufferBag = {};
4699
+ #textureBag = {};
4672
4700
  #wgpuMaterial;
4673
4701
  #buffers = new Map();
4674
4702
  #textures = new Map();
@@ -4683,16 +4711,23 @@ var Pacem;
4683
4711
  const flags = this.item.flags ?? [];
4684
4712
  let fresh = Pacem.Utils.isNull(this.#wgpuMaterial);
4685
4713
  if (flags.includes(Drawing3D.StalePropertyFlag.Material)) {
4714
+ this.#bufferBag = /* reset */ {};
4686
4715
  flags.splice(0);
4687
4716
  fresh = true;
4688
4717
  this.#textures.clear();
4689
4718
  this._resetMaterialBuffers();
4690
4719
  }
4720
+ const { pipeline } = context;
4721
+ const bag = (this.#bufferBag[key] ??= new Map());
4691
4722
  switch (key) {
4692
4723
  case 'material':
4693
4724
  case 'line':
4694
4725
  const buffer = this._ensureMaterialBuffer(context, key);
4695
4726
  if (buffer) {
4727
+ if (!bag.has(pipeline)) {
4728
+ fresh = true;
4729
+ bag.set(pipeline, buffer);
4730
+ }
4696
4731
  return Pacem.Utils.extend(buffer, { fresh });
4697
4732
  }
4698
4733
  return null;
@@ -4729,6 +4764,14 @@ var Pacem;
4729
4764
  }
4730
4765
  set.set(key, retval);
4731
4766
  fresh = true;
4767
+ //
4768
+ this.#textureBag = /* reset */ {};
4769
+ }
4770
+ const { pipeline } = ctx;
4771
+ const bag = (this.#textureBag[key] ??= new Map());
4772
+ if (!bag.has(pipeline)) {
4773
+ fresh = true;
4774
+ bag.set(pipeline, retval);
4732
4775
  }
4733
4776
  return Pacem.Utils.extend(retval, { fresh });
4734
4777
  }
@@ -4736,6 +4779,9 @@ var Pacem;
4736
4779
  this._destroyBuffers();
4737
4780
  }
4738
4781
  _destroyBuffers() {
4782
+ // memoizers
4783
+ this.#bufferBag = {};
4784
+ this.#textureBag = {};
4739
4785
  // buffers
4740
4786
  const buffers = this.#buffers.values();
4741
4787
  this.#buffers.clear(); // clear before destroying
@@ -4753,6 +4799,7 @@ var Pacem;
4753
4799
  time: 0, cursor: { x: 0, y: 0 }, resolution: { width: 0, height: 0 }
4754
4800
  };
4755
4801
  #buffer;
4802
+ #bufferBag = new Map();
4756
4803
  constructor(data) {
4757
4804
  super(data);
4758
4805
  Pacem.Utils.extend(this.#fields, data);
@@ -4771,21 +4818,33 @@ var Pacem;
4771
4818
  }
4772
4819
  _ensureInteractionBuffer(ctx, key = 'interaction') {
4773
4820
  const fields = this.#fields, item = this.item;
4774
- const fresh = (!this.#buffer
4821
+ let fresh = (!this.#buffer
4775
4822
  || item.time !== fields.time
4776
- || item.cursor?.x !== fields.cursor.x
4777
- || item.cursor?.y !== fields.cursor.y
4778
4823
  || item.resolution?.width !== fields.resolution.width
4779
4824
  || item.resolution?.height !== fields.resolution.height);
4825
+ if (!fresh && !Pacem.Utils.isNull(item.cursor)) {
4826
+ fresh = item.cursor.x !== fields.cursor.x
4827
+ || item.cursor.y !== fields.cursor.y;
4828
+ }
4780
4829
  if (fresh) {
4781
4830
  // [4bytes cursor.x, 4bytes cursor.y, 4bytes resolution.width, 4bytes resolution.height, 4bytes time] = 20 bytes total]
4782
4831
  const value = new Float32Array([item.cursor?.x ?? 0, item.cursor?.y ?? 0, item.resolution.width, item.resolution.height, item.time, /* padding */ .0]);
4783
4832
  const buffer = WebGPU.Buffers.createUniform(ctx.device, value, WebGPU.LABEL_PREFIX + 'interaction-buffer');
4784
4833
  this.#buffer = { buffer, value, version: performance.now() };
4834
+ this.#bufferBag.clear();
4835
+ }
4836
+ const { pipeline } = ctx;
4837
+ const bag = this.#bufferBag;
4838
+ if (!bag.has(pipeline)) {
4839
+ fresh = true;
4840
+ bag.set(pipeline, this.#buffer);
4785
4841
  }
4786
4842
  return Pacem.Utils.extend(this.#buffer, { fresh });
4787
4843
  }
4788
4844
  _destroyBuffers() {
4845
+ // memoizer
4846
+ this.#bufferBag.clear();
4847
+ // buffer itself
4789
4848
  const obsolete = this.#buffer;
4790
4849
  if (!Pacem.Utils.isNull(obsolete)) {
4791
4850
  this.destroySafely(obsolete);
@@ -4806,6 +4865,7 @@ var Pacem;
4806
4865
  #freshness = {
4807
4866
  geometry: true, material: true, transform: true
4808
4867
  };
4868
+ #worldTransformBufferBag = new Map();
4809
4869
  constructor(mesh, parent, geometries, materials) {
4810
4870
  super(mesh, parent);
4811
4871
  mesh.flags ??= [];
@@ -4829,6 +4889,7 @@ var Pacem;
4829
4889
  const freshness = this.#freshness;
4830
4890
  const flags = this.allFlags();
4831
4891
  if (Pacem.Utils.isNull(this.#worldTransform) || flags.includes(Drawing3D.StalePropertyFlag.Position) || flags.includes(Drawing3D.StalePropertyFlag.Transform)) {
4892
+ this.#worldTransformBufferBag.clear();
4832
4893
  // world transform bind group buffer
4833
4894
  freshness.transform = true;
4834
4895
  this._rebuildWorldMatrices(context);
@@ -4857,7 +4918,12 @@ var Pacem;
4857
4918
  case 'objectWorldTransform':
4858
4919
  const mat = this.#worldTransform, wFresh = freshness.transform;
4859
4920
  freshness.transform = false;
4860
- return Pacem.Utils.extend(mat, { fresh: wFresh });
4921
+ const bag = this.#worldTransformBufferBag, { pipeline } = context;
4922
+ const newInPipeline = !bag.has(pipeline);
4923
+ if (newInPipeline) {
4924
+ bag.set(pipeline, mat);
4925
+ }
4926
+ return Pacem.Utils.extend(mat, { fresh: wFresh || newInPipeline });
4861
4927
  default:
4862
4928
  throwBufferRequestError(key, RenderableMeshBuffer);
4863
4929
  }
@@ -4923,6 +4989,8 @@ var Pacem;
4923
4989
  //}
4924
4990
  }
4925
4991
  dispose() {
4992
+ // memoizer
4993
+ this.#worldTransformBufferBag.clear();
4926
4994
  const world = this.#worldTransform;
4927
4995
  this.#worldTransform = null;
4928
4996
  this.destroySafely(world);
@@ -4938,6 +5006,7 @@ var Pacem;
4938
5006
  // #region LIGHTS
4939
5007
  class RenderableLightBuffer extends RenderableBufferBase {
4940
5008
  #buffer;
5009
+ #bufferBag = new Map();
4941
5010
  constructor(light) {
4942
5011
  super(light);
4943
5012
  light.flags.push(Drawing3D.StalePropertyFlag.Light);
@@ -5021,17 +5090,25 @@ var Pacem;
5021
5090
  throw new Error("Method not implemented.");
5022
5091
  }
5023
5092
  specificBuffer(context, key) {
5024
- const fresh = Pacem.Utils.isNull(this.#buffer) || this.allFlags().length > 0;
5093
+ const bag = this.#bufferBag;
5094
+ let fresh = Pacem.Utils.isNull(this.#buffer) || this.allFlags().length > 0;
5025
5095
  if (fresh) {
5096
+ bag.clear();
5026
5097
  this._rebuildLight(context);
5027
5098
  }
5028
5099
  RenderableBuffer.clearFlags(this);
5100
+ const { pipeline } = context;
5101
+ if (!bag.has(pipeline)) {
5102
+ fresh = true;
5103
+ bag.set(pipeline, this.#buffer);
5104
+ }
5029
5105
  if (key === 'light') {
5030
5106
  return Pacem.Utils.extend(this.#buffer, { fresh });
5031
5107
  }
5032
5108
  throwBufferRequestError(key, RenderableLightBuffer);
5033
5109
  }
5034
5110
  dispose() {
5111
+ this.#bufferBag.clear();
5035
5112
  const buffer = this.#buffer;
5036
5113
  this.#buffer = null;
5037
5114
  this.destroySafely(buffer);
@@ -5470,7 +5547,9 @@ var Pacem;
5470
5547
  const { context, textureFormat: format } = this._buildContext(this.canvas, size);
5471
5548
  this._buildUpContext(device, adapter, context, format);
5472
5549
  // interaction
5473
- Pacem.Utils.extend(this.#interaction, { resolution: size });
5550
+ if (this.#hasModifiers) {
5551
+ Pacem.Utils.extend(this.#interaction, { resolution: size });
5552
+ }
5474
5553
  }
5475
5554
  }
5476
5555
  get canvas() {
@@ -5687,7 +5766,8 @@ var Pacem;
5687
5766
  */
5688
5767
  render(scene) {
5689
5768
  // do not render hidden stages
5690
- if (!(scene.size?.width > 0) || !(scene.size?.height > 0)) {
5769
+ const width = scene.size?.width, height = scene.size?.height;
5770
+ if (!(width > 0) || !(height > 0)) {
5691
5771
  return;
5692
5772
  }
5693
5773
  // retrieve stage renderer
@@ -5701,7 +5781,7 @@ var Pacem;
5701
5781
  }
5702
5782
  // draw
5703
5783
  const pixel = GETVAL(scene, WEBGPU_RAYCAST_PIXEL_PROP);
5704
- renderer.render({ cursor: pixel, time: performance.now() });
5784
+ renderer.render({ cursor: pixel, time: performance.now(), resolution: { width, height } });
5705
5785
  // raycast, just in case
5706
5786
  if (!scene.interactive) {
5707
5787
  return;