@expofp/renderer 3.1.2 → 3.1.4

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 (2) hide show
  1. package/dist/index.js +88 -70
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -310,6 +310,7 @@ var BatchedMesh$1 = class BatchedMesh$1 extends BatchedMesh {
310
310
  uniformsTexture;
311
311
  uniformSchema = {};
312
312
  isMaterialPatched = false;
313
+ boundsNeedsUpdate = false;
313
314
  batchCount = 0;
314
315
  indexBuffer;
315
316
  geometryById = /* @__PURE__ */ new Map();
@@ -408,6 +409,19 @@ var BatchedMesh$1 = class BatchedMesh$1 extends BatchedMesh {
408
409
  }
409
410
  this.uniformsTexture.setUniformAt(instanceId, name, value);
410
411
  }
412
+ updateMatrixWorld(force) {
413
+ super.updateMatrixWorld(force);
414
+ if (this.boundsNeedsUpdate) {
415
+ this.computeBoundingBox();
416
+ this.computeBoundingSphere();
417
+ this.boundsNeedsUpdate = false;
418
+ }
419
+ }
420
+ setMatrixAt(instanceId, matrix) {
421
+ super.setMatrixAt(instanceId, matrix);
422
+ this.boundsNeedsUpdate = true;
423
+ return this;
424
+ }
411
425
  dispose() {
412
426
  if (this.indexBuffer) this.geometry.setIndex(this.indexBuffer);
413
427
  super.dispose();
@@ -1485,7 +1499,7 @@ var ImageSystem = class extends RenderableSystem {
1485
1499
  /** Textures memory limit in megabytes */
1486
1500
  memoryLimitMb;
1487
1501
  packer;
1488
- originalAtlases = /* @__PURE__ */ new Map();
1502
+ atlasData = /* @__PURE__ */ new Map();
1489
1503
  globalTranslationMatrix = new Matrix4();
1490
1504
  originTranslationMatrix = new Matrix4();
1491
1505
  rotationMatrix = new Matrix4();
@@ -1503,11 +1517,11 @@ var ImageSystem = class extends RenderableSystem {
1503
1517
  }
1504
1518
  dispose() {
1505
1519
  super.dispose();
1506
- this.originalAtlases.clear();
1520
+ this.atlasData.clear();
1507
1521
  }
1508
1522
  updateLayerImpl(group, layerDef) {
1509
1523
  super.updateLayerImpl(group, layerDef);
1510
- if (this.memoryLimitMb) this.resizeTextures();
1524
+ this.renderAtlases();
1511
1525
  }
1512
1526
  buildLayer(layer) {
1513
1527
  const is3D = layer.mode === "3D";
@@ -1522,9 +1536,8 @@ var ImageSystem = class extends RenderableSystem {
1522
1536
  originalIndex: imageWithIndex.originalIndex
1523
1537
  }))).sort((a, b) => a.originalIndex - b.originalIndex);
1524
1538
  const instanceCount = rectsWithDef.length;
1525
- const texture = createAtlas(bin);
1526
1539
  const instanceMaterial = this.materialSystem.createTextureMaterial({
1527
- map: texture,
1540
+ map: createPlaceholderTexture(),
1528
1541
  uvOffset: true,
1529
1542
  depthEnable: is3D
1530
1543
  });
@@ -1532,6 +1545,7 @@ var ImageSystem = class extends RenderableSystem {
1532
1545
  const vertexCount = instanceGeometry.attributes["position"].count;
1533
1546
  const batchedMesh = new BatchedMesh$1(instanceCount, vertexCount, instanceGeometry.index?.count ?? 0, instanceMaterial);
1534
1547
  batchedMesh.sortObjects = false;
1548
+ batchedMesh.visible = false;
1535
1549
  batchedMesh.addPerInstanceUniforms({ vertex: { uvOffset: "vec4" } });
1536
1550
  const geometryId = batchedMesh.addGeometry(instanceGeometry);
1537
1551
  for (const { def, rect } of rectsWithDef) {
@@ -1540,66 +1554,40 @@ var ImageSystem = class extends RenderableSystem {
1540
1554
  batchedMesh.setUniformAt(instanceId, "uvOffset", uvOffset);
1541
1555
  this.registerDefObject(def, batchedMesh, instanceId);
1542
1556
  }
1543
- if (!rectsWithDef.some(({ def }) => def.source instanceof HTMLCanvasElement)) this.originalAtlases.set(batchedMesh, texture.image);
1557
+ const resizable = !rectsWithDef.some(({ def }) => def.source instanceof HTMLCanvasElement);
1558
+ this.atlasData.set(batchedMesh, {
1559
+ bin,
1560
+ resizable,
1561
+ appliedScale: 0
1562
+ });
1544
1563
  group.add(batchedMesh);
1545
1564
  }
1546
1565
  return group;
1547
1566
  }
1548
1567
  /**
1549
- * Resize textures to fit the memory limit.
1550
- * Uses stored original atlases so that every call computes a globally proportional
1551
- * resize factor, regardless of how many layers have been loaded so far.
1568
+ * Render (or re-render) atlas textures for all meshes, scaling to fit the memory limit when set.
1569
+ * Atlases are rendered directly at the target scale no full-size intermediate is created.
1570
+ * Meshes already at the target scale are skipped.
1552
1571
  */
1553
- resizeTextures() {
1554
- if (!this.memoryLimitMb) {
1555
- logger$12.debug("Memory limit is not set, unable to resize textures.");
1556
- return;
1557
- }
1558
- logger$12.debug(`Resizing textures to fit memory limit: ${this.memoryLimitMb} MB`);
1559
- const resizableMeshes = [];
1560
- let totalOriginal = 0;
1561
- let totalNonResizable = 0;
1572
+ renderAtlases() {
1573
+ const scale = this.computeResizeFactor();
1562
1574
  for (const mesh of this.getAllObjects()) {
1563
- const originalCanvas = this.originalAtlases.get(mesh);
1564
- const texture = mesh.material.map;
1565
- if (originalCanvas) {
1566
- totalOriginal += getCanvasSizeBytes(originalCanvas, texture.generateMipmaps);
1567
- resizableMeshes.push(mesh);
1568
- } else totalNonResizable += getCanvasSizeBytes(texture.image, texture.generateMipmaps);
1569
- }
1570
- if (resizableMeshes.length === 0) {
1571
- logger$12.debug("No resizable meshes found, no need to resize textures.");
1572
- return;
1573
- }
1574
- const budget = this.memoryLimitMb * 1024 * 1024 - totalNonResizable;
1575
- if (budget < 0) {
1576
- logger$12.debug("Memory limit is too low, unable to resize textures.");
1577
- return;
1578
- }
1579
- const resizeFactor = Math.sqrt(budget / totalOriginal);
1580
- if (resizeFactor >= 1) {
1581
- logger$12.debug("Textures are already within the memory limit, no need to resize");
1582
- return;
1583
- }
1584
- logger$12.debug(`Resize factor: ${resizeFactor}`);
1585
- let newTotal = totalNonResizable;
1586
- for (const mesh of resizableMeshes) {
1575
+ const data = this.atlasData.get(mesh);
1576
+ if (!data) continue;
1577
+ const targetScale = data.resizable ? scale : 1;
1578
+ if (data.appliedScale === targetScale) continue;
1587
1579
  const material = mesh.material;
1588
- const currentTexture = material.map;
1589
- const originalCanvas = this.originalAtlases.get(mesh);
1590
- const resizedTexture = resizeCanvas(originalCanvas, resizeFactor);
1591
- const originalDim = `${originalCanvas.width}x${originalCanvas.height}`;
1592
- const resizedDim = `${resizedTexture.image.width}x${resizedTexture.image.height}`;
1593
- logger$12.debug(`Resized atlas for ${mesh.name || mesh.parent?.name}, from ${originalDim} to ${resizedDim}`);
1594
- newTotal += getCanvasSizeBytes(resizedTexture.image, resizedTexture.generateMipmaps);
1595
- material.map = resizedTexture;
1580
+ const oldTexture = material.map;
1581
+ material.map = createAtlas(data.bin, targetScale);
1596
1582
  material.needsUpdate = true;
1597
- currentTexture.dispose();
1583
+ oldTexture?.dispose();
1584
+ mesh.visible = true;
1585
+ data.appliedScale = targetScale;
1586
+ logger$12.debug(`Rendered atlas for ${mesh.name || mesh.parent?.name} at scale ${targetScale.toFixed(3)}`);
1598
1587
  }
1599
- logger$12.debug(`New memory usage after resizing: ${newTotal} bytes`);
1600
1588
  }
1601
1589
  disposeObject(object) {
1602
- this.originalAtlases.delete(object);
1590
+ this.atlasData.delete(object);
1603
1591
  super.disposeObject(object);
1604
1592
  }
1605
1593
  updateDefImpl(imageDef, mesh, instanceIds) {
@@ -1613,6 +1601,32 @@ var ImageSystem = class extends RenderableSystem {
1613
1601
  const matrix = this.originTranslationMatrix.premultiply(this.scaleMatrix).premultiply(this.rotationMatrix).premultiply(this.globalTranslationMatrix);
1614
1602
  mesh.setMatrixAt(instanceId, matrix);
1615
1603
  }
1604
+ computeResizeFactor() {
1605
+ if (!this.memoryLimitMb) {
1606
+ logger$12.debug("Memory limit is not set, atlases will not be scaled");
1607
+ return 1;
1608
+ }
1609
+ let totalResizable = 0;
1610
+ let totalNonResizable = 0;
1611
+ for (const data of this.atlasData.values()) {
1612
+ const bytes = getAtlasSizeBytes(data.bin.width, data.bin.height);
1613
+ if (data.resizable) totalResizable += bytes;
1614
+ else totalNonResizable += bytes;
1615
+ }
1616
+ if (totalResizable === 0) {
1617
+ logger$12.debug("No resizable atlases, atlases will not be scaled");
1618
+ return 1;
1619
+ }
1620
+ const budget = this.memoryLimitMb * 1024 * 1024 - totalNonResizable;
1621
+ if (budget <= 0) {
1622
+ logger$12.debug("Memory limit is too low, unable to resize textures.");
1623
+ return 1;
1624
+ }
1625
+ const factor = Math.sqrt(budget / totalResizable);
1626
+ if (factor >= 1) return 1;
1627
+ logger$12.debug(`Resize factor: ${factor.toFixed(3)} (budget ${budget} bytes, resizable ${totalResizable} bytes)`);
1628
+ return factor;
1629
+ }
1616
1630
  packImages(images) {
1617
1631
  this.packer.reset();
1618
1632
  const rectangles = [];
@@ -1646,23 +1660,19 @@ var ImageSystem = class extends RenderableSystem {
1646
1660
  return this.packer.bins;
1647
1661
  }
1648
1662
  };
1649
- function createAtlas(bin) {
1663
+ function createAtlas(bin, scale) {
1650
1664
  const t0 = performance.now();
1651
1665
  const canvas = document.createElement("canvas");
1652
- canvas.width = bin.width;
1653
- canvas.height = bin.height;
1666
+ canvas.width = Math.max(1, Math.floor(bin.width * scale));
1667
+ canvas.height = Math.max(1, Math.floor(bin.height * scale));
1654
1668
  const ctx = canvas.getContext("2d");
1655
- for (const rect of bin.rects) ctx.drawImage(rect.data[0].def.source, rect.x, rect.y, rect.width, rect.height);
1669
+ for (const rect of bin.rects) ctx.drawImage(rect.data[0].def.source, Math.floor(rect.x * scale), Math.floor(rect.y * scale), Math.floor(rect.width * scale), Math.floor(rect.height * scale));
1656
1670
  const t1 = performance.now();
1657
- logger$12.debug(`Create atlas took ${(t1 - t0).toFixed(2)} milliseconds.`);
1671
+ logger$12.debug(`Create atlas (${canvas.width}x${canvas.height}) took ${(t1 - t0).toFixed(2)} milliseconds.`);
1658
1672
  return createTexture(canvas);
1659
1673
  }
1660
- function resizeCanvas(source, resizeFactor) {
1661
- const canvas = document.createElement("canvas");
1662
- canvas.width = Math.floor(source.width * resizeFactor);
1663
- canvas.height = Math.floor(source.height * resizeFactor);
1664
- canvas.getContext("2d").drawImage(source, 0, 0, canvas.width, canvas.height);
1665
- return createTexture(canvas);
1674
+ function createPlaceholderTexture() {
1675
+ return new Texture(document.createElement("canvas"));
1666
1676
  }
1667
1677
  function createTexture(source) {
1668
1678
  const texture = new Texture(source);
@@ -1672,8 +1682,8 @@ function createTexture(source) {
1672
1682
  texture.needsUpdate = true;
1673
1683
  return texture;
1674
1684
  }
1675
- function getCanvasSizeBytes(canvas, useMipmaps) {
1676
- return Math.ceil(canvas.width * canvas.height * 4 * (useMipmaps ? 1.33 : 1));
1685
+ function getAtlasSizeBytes(width, height) {
1686
+ return Math.ceil(width * height * 4 * 1.33);
1677
1687
  }
1678
1688
  //#endregion
1679
1689
  //#region src/geometry/line.ts
@@ -2511,10 +2521,8 @@ var LayerSystem = class {
2511
2521
  for (const child of sceneDef.rootLayer.children) rootGroup.add(this.buildLayer(child));
2512
2522
  this.updateLayer(sceneDef.rootLayer, false);
2513
2523
  printTree(rootGroup, logger$8.debug);
2514
- if (sceneDef.memoryLimit) {
2515
- this.imageSystem.memoryLimitMb = sceneDef.memoryLimit;
2516
- this.imageSystem.resizeTextures();
2517
- }
2524
+ if (sceneDef.memoryLimit) this.imageSystem.memoryLimitMb = sceneDef.memoryLimit;
2525
+ this.imageSystem.renderAtlases();
2518
2526
  return rootGroup;
2519
2527
  }
2520
2528
  /**
@@ -6125,6 +6133,16 @@ var PitchHandler = class extends Handler {
6125
6133
  p0 = new Vector2();
6126
6134
  p1 = new Vector2();
6127
6135
  prevTwoFingerAction;
6136
+ /**
6137
+ * @param domElement {@link HTMLElement} instance
6138
+ * @param eventManager {@link EventManager} instance
6139
+ * @param cameraAccess {@link InternalCameraAccess} instance
6140
+ * @param coordinatesSystem {@link CoordinatesSystem} instance
6141
+ */
6142
+ constructor(domElement, eventManager, cameraAccess, coordinatesSystem) {
6143
+ super(domElement, eventManager, cameraAccess, coordinatesSystem);
6144
+ this.updatePolarAngles();
6145
+ }
6128
6146
  reset(enableTransition = true) {
6129
6147
  const polarAngle = this.enabled ? this.minPitch * DEG2RAD : 0;
6130
6148
  return this.controller.rotatePolarTo(polarAngle, enableTransition);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@expofp/renderer",
3
- "version": "3.1.2",
3
+ "version": "3.1.4",
4
4
  "type": "module",
5
5
  "files": [
6
6
  "dist"