@ifc-lite/renderer 1.39.0 → 1.40.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/dist/deviation/deviation-pipeline.d.ts +8 -0
  2. package/dist/deviation/deviation-pipeline.d.ts.map +1 -1
  3. package/dist/deviation/deviation-pipeline.js +20 -9
  4. package/dist/deviation/deviation-pipeline.js.map +1 -1
  5. package/dist/deviation/deviation-shader.wgsl.d.ts +1 -1
  6. package/dist/deviation/deviation-shader.wgsl.d.ts.map +1 -1
  7. package/dist/deviation/deviation-shader.wgsl.js +11 -3
  8. package/dist/deviation/deviation-shader.wgsl.js.map +1 -1
  9. package/dist/index.d.ts +45 -1
  10. package/dist/index.d.ts.map +1 -1
  11. package/dist/index.js +78 -3
  12. package/dist/index.js.map +1 -1
  13. package/dist/picker.d.ts +9 -0
  14. package/dist/picker.d.ts.map +1 -1
  15. package/dist/picker.js +84 -2
  16. package/dist/picker.js.map +1 -1
  17. package/dist/pointcloud/point-cloud-node.d.ts +46 -0
  18. package/dist/pointcloud/point-cloud-node.d.ts.map +1 -1
  19. package/dist/pointcloud/point-cloud-node.js +71 -0
  20. package/dist/pointcloud/point-cloud-node.js.map +1 -1
  21. package/dist/pointcloud/point-cloud-ray-transform.d.ts +66 -0
  22. package/dist/pointcloud/point-cloud-ray-transform.d.ts.map +1 -0
  23. package/dist/pointcloud/point-cloud-ray-transform.js +172 -0
  24. package/dist/pointcloud/point-cloud-ray-transform.js.map +1 -0
  25. package/dist/pointcloud/point-cloud-renderer.d.ts +24 -0
  26. package/dist/pointcloud/point-cloud-renderer.d.ts.map +1 -1
  27. package/dist/pointcloud/point-cloud-renderer.js +46 -13
  28. package/dist/pointcloud/point-cloud-renderer.js.map +1 -1
  29. package/dist/pointcloud/point-cloud-spatial-index.d.ts +188 -0
  30. package/dist/pointcloud/point-cloud-spatial-index.d.ts.map +1 -0
  31. package/dist/pointcloud/point-cloud-spatial-index.js +536 -0
  32. package/dist/pointcloud/point-cloud-spatial-index.js.map +1 -0
  33. package/dist/pointcloud/point-cloud-uniforms.d.ts.map +1 -1
  34. package/dist/pointcloud/point-cloud-uniforms.js +14 -6
  35. package/dist/pointcloud/point-cloud-uniforms.js.map +1 -1
  36. package/dist/raycast-engine.d.ts +8 -0
  37. package/dist/raycast-engine.d.ts.map +1 -1
  38. package/dist/raycast-engine.js +68 -23
  39. package/dist/raycast-engine.js.map +1 -1
  40. package/dist/raycast-point-cloud-query.d.ts +122 -0
  41. package/dist/raycast-point-cloud-query.d.ts.map +1 -0
  42. package/dist/raycast-point-cloud-query.js +145 -0
  43. package/dist/raycast-point-cloud-query.js.map +1 -0
  44. package/dist/scene.d.ts.map +1 -1
  45. package/dist/scene.js +80 -46
  46. package/dist/scene.js.map +1 -1
  47. package/dist/snap-detector.d.ts +12 -1
  48. package/dist/snap-detector.d.ts.map +1 -1
  49. package/dist/snap-detector.js +9 -1
  50. package/dist/snap-detector.js.map +1 -1
  51. package/package.json +2 -2
package/dist/scene.js CHANGED
@@ -1761,56 +1761,90 @@ export class Scene {
1761
1761
  const oldFragments = this.streamingFragments;
1762
1762
  const oldBatches = this.batchedMeshes;
1763
1763
  const fragmentSet = new Set(oldFragments);
1764
- this.streamingFragments = [];
1765
- // 1. Collect ALL accumulated meshData before clearing state.
1766
- // Cold buckets (issue #1682 phase 3b) hold NO meshData their
1767
- // geometry lives on disk so they are carried through the rebuild as
1768
- // sealed shells instead of being re-grouped (re-grouping would
1769
- // silently drop them).
1770
- const allMeshData = [];
1771
- const carriedCold = [];
1772
- for (const [key, bucket] of this.buckets) {
1773
- if (this.coldBuckets.has(key) && bucket.meshData.length === 0 && bucket.batchedMesh) {
1774
- carriedCold.push([key, bucket]);
1775
- continue;
1764
+ const oldBatchSet = new Set(oldBatches);
1765
+ // Steps 1-4 detach the old drawables (streamingFragments = [],
1766
+ // batchedMeshes = []) BEFORE the replacement GPU buffers exist. If a
1767
+ // createBuffer fails part-way through, callers that CONTAIN the throw to
1768
+ // keep the canvas alive would otherwise be left rendering a half-built
1769
+ // often empty — scene, turning a crash into a silently blank model.
1770
+ let rebuilt = false;
1771
+ try {
1772
+ this.streamingFragments = [];
1773
+ // 1. Collect ALL accumulated meshData before clearing state.
1774
+ // Cold buckets (issue #1682 phase 3b) hold NO meshData — their
1775
+ // geometry lives on disk — so they are carried through the rebuild as
1776
+ // sealed shells instead of being re-grouped (re-grouping would
1777
+ // silently drop them).
1778
+ const allMeshData = [];
1779
+ const carriedCold = [];
1780
+ for (const [key, bucket] of this.buckets) {
1781
+ if (this.coldBuckets.has(key) && bucket.meshData.length === 0 && bucket.batchedMesh) {
1782
+ carriedCold.push([key, bucket]);
1783
+ continue;
1784
+ }
1785
+ for (const md of bucket.meshData)
1786
+ allMeshData.push(md);
1787
+ }
1788
+ // 2. Clear all bucket/batch state for a clean rebuild
1789
+ // NOTE: batchedMeshes keeps the OLD array reference — the renderer
1790
+ // continues to draw from it until we swap in the new array below.
1791
+ this.buckets.clear();
1792
+ this.meshDataBucket = new Map();
1793
+ this.activeBucketKey.clear();
1794
+ this.lastDrawnFrame.clear();
1795
+ this.residencyRestoreQueue.clear();
1796
+ this.pendingBatchKeys.clear();
1797
+ // Re-seat the carried cold shells in the fresh bucket map (their GPU
1798
+ // shells re-enter the flat array via rebuildPendingBatches below).
1799
+ for (const [key, bucket] of carriedCold)
1800
+ this.buckets.set(key, bucket);
1801
+ // 3. Re-group ALL meshData by their CURRENT color (and grid cell).
1802
+ // meshData.color may have been mutated in-place since the mesh was
1803
+ // first bucketed, so the original bucket key is stale. Re-grouping
1804
+ // by current color ensures batches render with correct colors.
1805
+ for (const meshData of allMeshData) {
1806
+ const baseKey = this.bucketBaseKey(meshData);
1807
+ const bucketKey = this.resolveActiveBucket(baseKey, meshData);
1808
+ let bucket = this.buckets.get(bucketKey);
1809
+ if (!bucket) {
1810
+ bucket = { key: bucketKey, meshData: [], batchedMesh: null, vertexBytes: 0 };
1811
+ this.buckets.set(bucketKey, bucket);
1812
+ }
1813
+ bucket.meshData.push(meshData);
1814
+ this.meshDataBucket.set(meshData, bucket);
1815
+ this.pendingBatchKeys.add(bucketKey);
1776
1816
  }
1777
- for (const md of bucket.meshData)
1778
- allMeshData.push(md);
1817
+ // 4. Build new proper batches into a fresh array
1818
+ this.batchedMeshes = [];
1819
+ this.rebuildPendingBatches(device, pipeline);
1820
+ rebuilt = true;
1821
+ // Cached partial (filtered-visibility) batches are keyed by their SOURCE
1822
+ // batch, so they only go stale once the replacement batches are live.
1823
+ // Dropping them up in step 2 destroyed their GPU resources BEFORE the
1824
+ // rebuild could fail, and the rollback cannot bring them back — an active
1825
+ // hide/isolate view lost its visible subset and had to recreate it
1826
+ // against the very device that just failed. On the failure path they now
1827
+ // survive, still matching the restored batches.
1828
+ this.dropAllPartialCaches();
1779
1829
  }
1780
- // 2. Clear all bucket/batch state for a clean rebuild
1781
- // NOTE: batchedMeshes keeps the OLD array reference — the renderer
1782
- // continues to draw from it until we swap in the new array below.
1783
- this.buckets.clear();
1784
- this.meshDataBucket = new Map();
1785
- this.activeBucketKey.clear();
1786
- this.lastDrawnFrame.clear();
1787
- this.residencyRestoreQueue.clear();
1788
- this.pendingBatchKeys.clear();
1789
- // Destroy cached partial batches — their colorKeys are now stale
1790
- this.dropAllPartialCaches();
1791
- // Re-seat the carried cold shells in the fresh bucket map (their GPU
1792
- // shells re-enter the flat array via rebuildPendingBatches below).
1793
- for (const [key, bucket] of carriedCold)
1794
- this.buckets.set(key, bucket);
1795
- // 3. Re-group ALL meshData by their CURRENT color (and grid cell).
1796
- // meshData.color may have been mutated in-place since the mesh was
1797
- // first bucketed, so the original bucket key is stale. Re-grouping
1798
- // by current color ensures batches render with correct colors.
1799
- for (const meshData of allMeshData) {
1800
- const baseKey = this.bucketBaseKey(meshData);
1801
- const bucketKey = this.resolveActiveBucket(baseKey, meshData);
1802
- let bucket = this.buckets.get(bucketKey);
1803
- if (!bucket) {
1804
- bucket = { key: bucketKey, meshData: [], batchedMesh: null, vertexBytes: 0 };
1805
- this.buckets.set(bucketKey, bucket);
1830
+ finally {
1831
+ if (!rebuilt) {
1832
+ // Free ONLY what this attempt created. Carried cold shells are aliased
1833
+ // into BOTH the old and the new array, so anything that was already
1834
+ // live before the rebuild must be left alone — destroying it would
1835
+ // leave the restored arrays pointing at dead buffers.
1836
+ for (const created of this.batchedMeshes) {
1837
+ if (!oldBatchSet.has(created) && !fragmentSet.has(created)) {
1838
+ destroyGpuResources(created);
1839
+ }
1840
+ }
1841
+ // Step 5 never ran, so every old fragment/batch is still a live GPU
1842
+ // resource: putting the arrays back restores exactly what was on
1843
+ // screen.
1844
+ this.streamingFragments = oldFragments;
1845
+ this.batchedMeshes = oldBatches;
1806
1846
  }
1807
- bucket.meshData.push(meshData);
1808
- this.meshDataBucket.set(meshData, bucket);
1809
- this.pendingBatchKeys.add(bucketKey);
1810
1847
  }
1811
- // 4. Build new proper batches into a fresh array
1812
- this.batchedMeshes = [];
1813
- this.rebuildPendingBatches(device, pipeline);
1814
1848
  // 5. NOW destroy old fragment/batch GPU resources (new batches are live)
1815
1849
  for (const fragment of oldFragments)
1816
1850
  destroyGpuResources(fragment);