@ifc-lite/pointcloud 0.10.0 → 0.12.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 (84) hide show
  1. package/README.md +72 -0
  2. package/dist/copc/copc-hierarchy.d.ts +102 -0
  3. package/dist/copc/copc-hierarchy.d.ts.map +1 -0
  4. package/dist/copc/copc-hierarchy.js +210 -0
  5. package/dist/copc/copc-hierarchy.js.map +1 -0
  6. package/dist/copc/copc-info.d.ts +52 -0
  7. package/dist/copc/copc-info.d.ts.map +1 -0
  8. package/dist/copc/copc-info.js +147 -0
  9. package/dist/copc/copc-info.js.map +1 -0
  10. package/dist/copc/copc-reader.d.ts +60 -0
  11. package/dist/copc/copc-reader.d.ts.map +1 -0
  12. package/dist/copc/copc-reader.js +138 -0
  13. package/dist/copc/copc-reader.js.map +1 -0
  14. package/dist/copc/copc-worker-client.d.ts +37 -0
  15. package/dist/copc/copc-worker-client.d.ts.map +1 -0
  16. package/dist/copc/copc-worker-client.js +154 -0
  17. package/dist/copc/copc-worker-client.js.map +1 -0
  18. package/dist/copc/copc-worker-host.d.ts +11 -0
  19. package/dist/copc/copc-worker-host.d.ts.map +1 -0
  20. package/dist/copc/copc-worker-host.js +73 -0
  21. package/dist/copc/copc-worker-host.js.map +1 -0
  22. package/dist/formats/las.d.ts +1 -0
  23. package/dist/formats/las.d.ts.map +1 -1
  24. package/dist/formats/las.js +1 -1
  25. package/dist/formats/las.js.map +1 -1
  26. package/dist/index.d.ts +11 -1
  27. package/dist/index.d.ts.map +1 -1
  28. package/dist/index.js +10 -1
  29. package/dist/index.js.map +1 -1
  30. package/dist/lod/copc-lod-tree.d.ts +15 -0
  31. package/dist/lod/copc-lod-tree.d.ts.map +1 -0
  32. package/dist/lod/copc-lod-tree.js +67 -0
  33. package/dist/lod/copc-lod-tree.js.map +1 -0
  34. package/dist/lod/frustum.d.ts +13 -0
  35. package/dist/lod/frustum.d.ts.map +1 -0
  36. package/dist/lod/frustum.js +38 -0
  37. package/dist/lod/frustum.js.map +1 -0
  38. package/dist/lod/pacer.d.ts +62 -0
  39. package/dist/lod/pacer.d.ts.map +1 -0
  40. package/dist/lod/pacer.js +56 -0
  41. package/dist/lod/pacer.js.map +1 -0
  42. package/dist/lod/select.d.ts +80 -0
  43. package/dist/lod/select.d.ts.map +1 -0
  44. package/dist/lod/select.js +155 -0
  45. package/dist/lod/select.js.map +1 -0
  46. package/dist/streaming/blob-source.d.ts +3 -2
  47. package/dist/streaming/blob-source.d.ts.map +1 -1
  48. package/dist/streaming/blob-source.js +2 -9
  49. package/dist/streaming/blob-source.js.map +1 -1
  50. package/dist/streaming/decode-worker.js +22 -0
  51. package/dist/streaming/decode-worker.js.map +1 -1
  52. package/dist/streaming/e57-logical-range.d.ts +20 -2
  53. package/dist/streaming/e57-logical-range.d.ts.map +1 -1
  54. package/dist/streaming/e57-logical-range.js +32 -8
  55. package/dist/streaming/e57-logical-range.js.map +1 -1
  56. package/dist/streaming/e57-metadata.d.ts.map +1 -1
  57. package/dist/streaming/e57-metadata.js +3 -1
  58. package/dist/streaming/e57-metadata.js.map +1 -1
  59. package/dist/streaming/e57-source.d.ts.map +1 -1
  60. package/dist/streaming/e57-source.js +6 -1
  61. package/dist/streaming/e57-source.js.map +1 -1
  62. package/dist/streaming/http-range-source.d.ts +47 -0
  63. package/dist/streaming/http-range-source.d.ts.map +1 -0
  64. package/dist/streaming/http-range-source.js +102 -0
  65. package/dist/streaming/http-range-source.js.map +1 -0
  66. package/dist/streaming/inline-worker.js +1 -1
  67. package/dist/streaming/laz-perf-loader.d.ts +58 -0
  68. package/dist/streaming/laz-perf-loader.d.ts.map +1 -0
  69. package/dist/streaming/laz-perf-loader.js +107 -0
  70. package/dist/streaming/laz-perf-loader.js.map +1 -0
  71. package/dist/streaming/laz-source.d.ts +0 -40
  72. package/dist/streaming/laz-source.d.ts.map +1 -1
  73. package/dist/streaming/laz-source.js +1 -94
  74. package/dist/streaming/laz-source.js.map +1 -1
  75. package/dist/streaming/protocol.d.ts +45 -0
  76. package/dist/streaming/protocol.d.ts.map +1 -1
  77. package/dist/streaming/protocol.js.map +1 -1
  78. package/dist/streaming/types.d.ts +14 -0
  79. package/dist/streaming/types.d.ts.map +1 -1
  80. package/dist/streaming/worker-client.d.ts +25 -0
  81. package/dist/streaming/worker-client.d.ts.map +1 -1
  82. package/dist/streaming/worker-client.js +12 -5
  83. package/dist/streaming/worker-client.js.map +1 -1
  84. package/package.json +2 -2
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAIA;;;;;;;GAOG;AAEH,YAAY,EAAE,iBAAiB,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAGtF,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,EACL,iBAAiB,EACjB,kBAAkB,EAClB,KAAK,oBAAoB,EACzB,KAAK,qBAAqB,GAC3B,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EACL,eAAe,EACf,oBAAoB,EACpB,wBAAwB,GACzB,MAAM,2BAA2B,CAAC;AAGnC,OAAO,EACL,cAAc,EACd,eAAe,EACf,mBAAmB,EACnB,KAAK,SAAS,GACf,MAAM,kBAAkB,CAAC;AAG1B,YAAY,EACV,oBAAoB,EACpB,eAAe,EACf,0BAA0B,EAC1B,cAAc,GACf,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AACrF,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,EAAE,kBAAkB,EAAE,yBAAyB,EAAE,MAAM,2BAA2B,CAAC;AAC1F,OAAO,EACL,wBAAwB,EACxB,yBAAyB,EACzB,KAAK,gBAAgB,EACrB,KAAK,iBAAiB,EACtB,KAAK,kBAAkB,GACxB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,0BAA0B,EAAE,MAAM,oCAAoC,CAAC;AAChF,OAAO,EACL,iBAAiB,EACjB,yBAAyB,EACzB,sBAAsB,EACtB,KAAK,iBAAiB,EACtB,KAAK,iBAAiB,GACvB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7D,OAAO,EACL,kBAAkB,EAClB,WAAW,EACX,YAAY,IAAI,eAAe,EAC/B,SAAS,EACT,aAAa,EACb,KAAK,aAAa,EAClB,KAAK,WAAW,GACjB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAC5D,OAAO,EACL,wBAAwB,EACxB,KAAK,+BAA+B,EACpC,KAAK,mBAAmB,EACxB,KAAK,kBAAkB,GACxB,MAAM,8BAA8B,CAAC;AACtC,OAAO,EACL,gBAAgB,EAChB,KAAK,uBAAuB,EAC5B,KAAK,YAAY,GAClB,MAAM,qBAAqB,CAAC;AAG7B,OAAO,EACL,eAAe,EACf,qBAAqB,EACrB,0BAA0B,EAC1B,8BAA8B,EAC9B,0BAA0B,EAC1B,KAAK,wBAAwB,GAC9B,MAAM,qBAAqB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -9,7 +9,8 @@ export { POINTCLOUD_ATTR, POINTCLOUD_ATTR_KEYS, decodeIfcxPointAttribute, } from
9
9
  // LAS reader primitives
10
10
  export { parseLasHeader, decodeLasPoints, sampleMaxRgbChannel, } from './formats/las.js';
11
11
  export { LasStreamingSource } from './streaming/las-source.js';
12
- export { LazStreamingSource, probeLazPerfWasmLoad } from './streaming/laz-source.js';
12
+ export { LazStreamingSource } from './streaming/laz-source.js';
13
+ export { probeLazPerfWasmLoad } from './streaming/laz-perf-loader.js';
13
14
  export { PlyStreamingSource } from './streaming/ply-source.js';
14
15
  export { PcdStreamingSource } from './streaming/pcd-source.js';
15
16
  export { E57StreamingSource, inspectE57SpatialMetadata } from './streaming/e57-source.js';
@@ -23,4 +24,12 @@ export { createDecodeWorkerSource, } from './streaming/worker-client.js';
23
24
  export { streamPointCloud, } from './streaming/host.js';
24
25
  // LAS classification helpers (#1783)
25
26
  export { LAS_CLASS_COUNT, lasClassificationName, createClassificationCounts, accumulateClassificationCounts, classificationCountEntries, } from './classification.js';
27
+ export { HttpRangeSource } from './streaming/http-range-source.js';
28
+ export { COPC_PROBE_BYTES, isCopcHeader, copcNodeBounds, voxelKeyId, } from './copc/copc-info.js';
29
+ export { CopcHierarchy, copcChildKeys, } from './copc/copc-hierarchy.js';
30
+ export { openCopcWorkerReader, } from './copc/copc-worker-client.js';
31
+ // View-dependent LOD selection + progressive pacing, renderer-agnostic (#6869)
32
+ export { selectLod, } from './lod/select.js';
33
+ export { LodPacer, shouldReplacePass, } from './lod/pacer.js';
34
+ export { createCopcLodTree, } from './lod/copc-lod-tree.js';
26
35
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;+DAE+D;AAa/D,mCAAmC;AACnC,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,EACL,iBAAiB,EACjB,kBAAkB,GAGnB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EACL,eAAe,EACf,oBAAoB,EACpB,wBAAwB,GACzB,MAAM,2BAA2B,CAAC;AAEnC,wBAAwB;AACxB,OAAO,EACL,cAAc,EACd,eAAe,EACf,mBAAmB,GAEpB,MAAM,kBAAkB,CAAC;AAS1B,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AACrF,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,EAAE,kBAAkB,EAAE,yBAAyB,EAAE,MAAM,2BAA2B,CAAC;AAC1F,OAAO,EACL,wBAAwB,EACxB,yBAAyB,GAI1B,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,0BAA0B,EAAE,MAAM,oCAAoC,CAAC;AAChF,OAAO,EACL,iBAAiB,EACjB,yBAAyB,EACzB,sBAAsB,GAGvB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7D,OAAO,EACL,kBAAkB,EAClB,WAAW,EACX,YAAY,IAAI,eAAe,EAC/B,SAAS,EACT,aAAa,GAGd,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAC5D,OAAO,EACL,wBAAwB,GAIzB,MAAM,8BAA8B,CAAC;AACtC,OAAO,EACL,gBAAgB,GAGjB,MAAM,qBAAqB,CAAC;AAE7B,qCAAqC;AACrC,OAAO,EACL,eAAe,EACf,qBAAqB,EACrB,0BAA0B,EAC1B,8BAA8B,EAC9B,0BAA0B,GAE3B,MAAM,qBAAqB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;+DAE+D;AAa/D,mCAAmC;AACnC,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,EACL,iBAAiB,EACjB,kBAAkB,GAGnB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EACL,eAAe,EACf,oBAAoB,EACpB,wBAAwB,GACzB,MAAM,2BAA2B,CAAC;AAEnC,wBAAwB;AACxB,OAAO,EACL,cAAc,EACd,eAAe,EACf,mBAAmB,GAEpB,MAAM,kBAAkB,CAAC;AAS1B,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,EAAE,oBAAoB,EAAE,MAAM,gCAAgC,CAAC;AACtE,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,EAAE,kBAAkB,EAAE,yBAAyB,EAAE,MAAM,2BAA2B,CAAC;AAC1F,OAAO,EACL,wBAAwB,EACxB,yBAAyB,GAI1B,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,0BAA0B,EAAE,MAAM,oCAAoC,CAAC;AAChF,OAAO,EACL,iBAAiB,EACjB,yBAAyB,EACzB,sBAAsB,GAGvB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7D,OAAO,EACL,kBAAkB,EAClB,WAAW,EACX,YAAY,IAAI,eAAe,EAC/B,SAAS,EACT,aAAa,GAGd,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAC5D,OAAO,EACL,wBAAwB,GAIzB,MAAM,8BAA8B,CAAC;AACtC,OAAO,EACL,gBAAgB,GAGjB,MAAM,qBAAqB,CAAC;AAE7B,qCAAqC;AACrC,OAAO,EACL,eAAe,EACf,qBAAqB,EACrB,0BAA0B,EAC1B,8BAA8B,EAC9B,0BAA0B,GAE3B,MAAM,qBAAqB,CAAC;AAK7B,OAAO,EAAE,eAAe,EAA+B,MAAM,kCAAkC,CAAC;AAChG,OAAO,EACL,gBAAgB,EAChB,YAAY,EACZ,cAAc,EACd,UAAU,GAIX,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,aAAa,EACb,aAAa,GAMd,MAAM,0BAA0B,CAAC;AAClC,OAAO,EACL,oBAAoB,GAGrB,MAAM,8BAA8B,CAAC;AAEtC,+EAA+E;AAC/E,OAAO,EACL,SAAS,GAMV,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,QAAQ,EACR,iBAAiB,GAGlB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACL,iBAAiB,GAGlB,MAAM,wBAAwB,CAAC"}
@@ -0,0 +1,15 @@
1
+ import { type CopcInfo } from '../copc/copc-info.js';
2
+ import { type CopcHierarchy, type CopcNodeEntry, type CopcPageRef } from '../copc/copc-hierarchy.js';
3
+ import type { LodNode } from './select.js';
4
+ export interface CopcLodNode extends LodNode {
5
+ readonly entry: CopcNodeEntry;
6
+ readonly children: readonly CopcLodNode[] | null;
7
+ }
8
+ export interface CopcLodTree {
9
+ /** The root, or null when the hierarchy has no root node entry. */
10
+ readonly root: CopcLodNode | null;
11
+ /** Pending pages whose subtree roots are children of `node`. */
12
+ pendingPagesUnder(node: LodNode): CopcPageRef[];
13
+ }
14
+ export declare function createCopcLodTree(hierarchy: CopcHierarchy, info: CopcInfo, originOffset?: readonly [number, number, number]): CopcLodTree;
15
+ //# sourceMappingURL=copc-lod-tree.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"copc-lod-tree.d.ts","sourceRoot":"","sources":["../../src/lod/copc-lod-tree.ts"],"names":[],"mappings":"AAmBA,OAAO,EAA8B,KAAK,QAAQ,EAAiB,MAAM,sBAAsB,CAAC;AAChG,OAAO,EAAiB,KAAK,aAAa,EAAE,KAAK,aAAa,EAAE,KAAK,WAAW,EAAE,MAAM,2BAA2B,CAAC;AACpH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAE3C,MAAM,WAAW,WAAY,SAAQ,OAAO;IAC1C,QAAQ,CAAC,KAAK,EAAE,aAAa,CAAC;IAC9B,QAAQ,CAAC,QAAQ,EAAE,SAAS,WAAW,EAAE,GAAG,IAAI,CAAC;CAClD;AAED,MAAM,WAAW,WAAW;IAC1B,mEAAmE;IACnE,QAAQ,CAAC,IAAI,EAAE,WAAW,GAAG,IAAI,CAAC;IAClC,gEAAgE;IAChE,iBAAiB,CAAC,IAAI,EAAE,OAAO,GAAG,WAAW,EAAE,CAAC;CACjD;AAED,wBAAgB,iBAAiB,CAC/B,SAAS,EAAE,aAAa,EACxB,IAAI,EAAE,QAAQ,EACd,YAAY,CAAC,EAAE,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,GAC/C,WAAW,CAyCb"}
@@ -0,0 +1,67 @@
1
+ /* This Source Code Form is subject to the terms of the Mozilla Public
2
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
3
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
+ /**
5
+ * Presents a (partially loaded) COPC hierarchy as `LodNode`s (#6869).
6
+ *
7
+ * Node bounds come from the voxel key, in the frame the decoder emits points
8
+ * in: native coordinates minus `originOffset` (the same f64 subtraction the
9
+ * decoder applies). A host whose scene applies a further affine placement
10
+ * should move the CAMERA into this frame (view-projection times placement)
11
+ * rather than the boxes, which keeps them exact instead of re-boxed.
12
+ *
13
+ * A node whose children include the root of an unloaded hierarchy page
14
+ * reports `children: null`, so `selectLod` lists it in `needsChildren` and
15
+ * the host loads exactly those pages.
16
+ */
17
+ import { bboxInDecodedFrame } from '../formats/las.js';
18
+ import { copcNodeBounds, voxelKeyId } from '../copc/copc-info.js';
19
+ import { copcChildKeys } from '../copc/copc-hierarchy.js';
20
+ export function createCopcLodTree(hierarchy, info, originOffset) {
21
+ const cache = new Map();
22
+ const nodeFor = (key) => {
23
+ const id = voxelKeyId(key);
24
+ const cached = cache.get(id);
25
+ if (cached)
26
+ return cached;
27
+ const entry = hierarchy.nodes.get(id);
28
+ if (!entry)
29
+ return null;
30
+ const node = {
31
+ id,
32
+ entry,
33
+ bounds: bboxInDecodedFrame(copcNodeBounds(info, key), originOffset),
34
+ pointCount: entry.pointCount,
35
+ get children() {
36
+ const out = [];
37
+ for (const childKey of copcChildKeys(key)) {
38
+ const state = hierarchy.stateOf(childKey);
39
+ if (state === 'page')
40
+ return null;
41
+ if (state === 'node') {
42
+ const child = nodeFor(childKey);
43
+ if (child)
44
+ out.push(child);
45
+ }
46
+ }
47
+ return out;
48
+ },
49
+ };
50
+ cache.set(id, node);
51
+ return node;
52
+ };
53
+ return {
54
+ get root() {
55
+ return nodeFor({ d: 0, x: 0, y: 0, z: 0 });
56
+ },
57
+ pendingPagesUnder(node) {
58
+ const entry = cache.get(node.id)?.entry;
59
+ if (!entry)
60
+ return [];
61
+ return copcChildKeys(entry.key)
62
+ .map((k) => hierarchy.pendingPages.get(voxelKeyId(k)))
63
+ .filter((ref) => ref !== undefined);
64
+ },
65
+ };
66
+ }
67
+ //# sourceMappingURL=copc-lod-tree.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"copc-lod-tree.js","sourceRoot":"","sources":["../../src/lod/copc-lod-tree.ts"],"names":[],"mappings":"AAAA;;+DAE+D;AAE/D;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,EAAE,cAAc,EAAE,UAAU,EAAgC,MAAM,sBAAsB,CAAC;AAChG,OAAO,EAAE,aAAa,EAA4D,MAAM,2BAA2B,CAAC;AAepH,MAAM,UAAU,iBAAiB,CAC/B,SAAwB,EACxB,IAAc,EACd,YAAgD;IAEhD,MAAM,KAAK,GAAG,IAAI,GAAG,EAAuB,CAAC;IAC7C,MAAM,OAAO,GAAG,CAAC,GAAa,EAAsB,EAAE;QACpD,MAAM,EAAE,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC;QAC3B,MAAM,MAAM,GAAG,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAC7B,IAAI,MAAM;YAAE,OAAO,MAAM,CAAC;QAC1B,MAAM,KAAK,GAAG,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACtC,IAAI,CAAC,KAAK;YAAE,OAAO,IAAI,CAAC;QACxB,MAAM,IAAI,GAAgB;YACxB,EAAE;YACF,KAAK;YACL,MAAM,EAAE,kBAAkB,CAAC,cAAc,CAAC,IAAI,EAAE,GAAG,CAAC,EAAE,YAAY,CAAC;YACnE,UAAU,EAAE,KAAK,CAAC,UAAU;YAC5B,IAAI,QAAQ;gBACV,MAAM,GAAG,GAAkB,EAAE,CAAC;gBAC9B,KAAK,MAAM,QAAQ,IAAI,aAAa,CAAC,GAAG,CAAC,EAAE,CAAC;oBAC1C,MAAM,KAAK,GAAG,SAAS,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;oBAC1C,IAAI,KAAK,KAAK,MAAM;wBAAE,OAAO,IAAI,CAAC;oBAClC,IAAI,KAAK,KAAK,MAAM,EAAE,CAAC;wBACrB,MAAM,KAAK,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;wBAChC,IAAI,KAAK;4BAAE,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;oBAC7B,CAAC;gBACH,CAAC;gBACD,OAAO,GAAG,CAAC;YACb,CAAC;SACF,CAAC;QACF,KAAK,CAAC,GAAG,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;QACpB,OAAO,IAAI,CAAC;IACd,CAAC,CAAC;IACF,OAAO;QACL,IAAI,IAAI;YACN,OAAO,OAAO,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;QAC7C,CAAC;QACD,iBAAiB,CAAC,IAAa;YAC7B,MAAM,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,KAAK,CAAC;YACxC,IAAI,CAAC,KAAK;gBAAE,OAAO,EAAE,CAAC;YACtB,OAAO,aAAa,CAAC,KAAK,CAAC,GAAG,CAAC;iBAC5B,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,SAAS,CAAC,YAAY,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC;iBACrD,MAAM,CAAC,CAAC,GAAG,EAAsB,EAAE,CAAC,GAAG,KAAK,SAAS,CAAC,CAAC;QAC5D,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * View-frustum planes from a view-projection matrix (Gribb/Hartmann), for
3
+ * WebGPU clip space: x, y in [-w, w], z in [0, w]. Works for forward and
4
+ * reverse Z alike (the two depth planes just swap meaning) and drops a
5
+ * degenerate plane, which is what an infinite far plane produces.
6
+ */
7
+ import type { PointCloudBBox } from '../types.js';
8
+ /** `[a, b, c, d]`: a point p is inside when `a*x + b*y + c*z + d >= 0`. */
9
+ export type Plane = [number, number, number, number];
10
+ export declare function frustumPlanes(viewProj: ArrayLike<number>): Plane[];
11
+ /** False only when the box lies entirely outside one plane (conservative). */
12
+ export declare function boxIntersectsFrustum(box: PointCloudBBox, planes: readonly Plane[]): boolean;
13
+ //# sourceMappingURL=frustum.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"frustum.d.ts","sourceRoot":"","sources":["../../src/lod/frustum.ts"],"names":[],"mappings":"AAIA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAElD,2EAA2E;AAC3E,MAAM,MAAM,KAAK,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;AAOrD,wBAAgB,aAAa,CAAC,QAAQ,EAAE,SAAS,CAAC,MAAM,CAAC,GAAG,KAAK,EAAE,CAgBlE;AAED,8EAA8E;AAC9E,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,cAAc,EAAE,MAAM,EAAE,SAAS,KAAK,EAAE,GAAG,OAAO,CAS3F"}
@@ -0,0 +1,38 @@
1
+ /* This Source Code Form is subject to the terms of the Mozilla Public
2
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
3
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
+ /** Column-major 4x4 element (row r, column c). */
5
+ function at(m, r, c) {
6
+ return m[c * 4 + r];
7
+ }
8
+ export function frustumPlanes(viewProj) {
9
+ const row = (r) => [at(viewProj, r, 0), at(viewProj, r, 1), at(viewProj, r, 2), at(viewProj, r, 3)];
10
+ const [r0, r1, r2, r3] = [row(0), row(1), row(2), row(3)];
11
+ const add = (a, b, s) => [a[0] + s * b[0], a[1] + s * b[1], a[2] + s * b[2], a[3] + s * b[3]];
12
+ const candidates = [
13
+ add(r3, r0, 1), add(r3, r0, -1), // left, right
14
+ add(r3, r1, 1), add(r3, r1, -1), // bottom, top
15
+ r2, add(r3, r2, -1), // z >= 0, z <= w
16
+ ];
17
+ const planes = [];
18
+ for (const p of candidates) {
19
+ const len = Math.hypot(p[0], p[1], p[2]);
20
+ if (!(len > 1e-12) || !Number.isFinite(len))
21
+ continue;
22
+ planes.push([p[0] / len, p[1] / len, p[2] / len, p[3] / len]);
23
+ }
24
+ return planes;
25
+ }
26
+ /** False only when the box lies entirely outside one plane (conservative). */
27
+ export function boxIntersectsFrustum(box, planes) {
28
+ for (const [a, b, c, d] of planes) {
29
+ // The box corner furthest along the plane normal.
30
+ const x = a >= 0 ? box.max[0] : box.min[0];
31
+ const y = b >= 0 ? box.max[1] : box.min[1];
32
+ const z = c >= 0 ? box.max[2] : box.min[2];
33
+ if (a * x + b * y + c * z + d < 0)
34
+ return false;
35
+ }
36
+ return true;
37
+ }
38
+ //# sourceMappingURL=frustum.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"frustum.js","sourceRoot":"","sources":["../../src/lod/frustum.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,62 @@
1
+ /**
2
+ * Progressive-refinement pacing for LOD streaming (#6869). Pure: callers
3
+ * pass in measured durations; nothing here reads a clock.
4
+ *
5
+ * After a camera move the first pass should land quickly, so its point
6
+ * budget is sized to a time budget (default 200 ms) from a learned read
7
+ * rate (points decoded and uploaded per millisecond). The estimate is an
8
+ * asymmetric EMA: it drops fast when reads get slower (a congested network
9
+ * should shrink the next first pass at once) and rises slowly when they get
10
+ * faster (one cache-warm read must not inflate it). Each sample is first
11
+ * clipped to `[rate / clipRatio, rate * clipRatio]`, so a single outlier, a
12
+ * stall in a background tab or a near-zero duration, moves the estimate by
13
+ * a bounded step.
14
+ */
15
+ export interface LodPacerOptions {
16
+ /** Target duration of the first pass, ms. Default 200. */
17
+ firstPassMs?: number;
18
+ /** Prior read rate before any observation, points/ms. Default 1000. */
19
+ initialPointsPerMs?: number;
20
+ /** Floor for the first pass so it is never empty. Default 50 000. */
21
+ minFirstPassPoints?: number;
22
+ /** EMA weight when a sample is slower than the estimate. Default 0.5. */
23
+ fallAlpha?: number;
24
+ /** EMA weight when a sample is faster than the estimate. Default 0.1. */
25
+ riseAlpha?: number;
26
+ /** Outlier clip factor around the current estimate. Default 4. */
27
+ clipRatio?: number;
28
+ }
29
+ export declare class LodPacer {
30
+ private rate;
31
+ private readonly firstPassMs;
32
+ private readonly minFirstPassPoints;
33
+ private readonly fallAlpha;
34
+ private readonly riseAlpha;
35
+ private readonly clipRatio;
36
+ constructor(options?: LodPacerOptions);
37
+ /** Current read-rate estimate, points per millisecond. */
38
+ get pointsPerMs(): number;
39
+ /** Record that `points` were read in `elapsedMs`. Uninformative samples are ignored. */
40
+ observe(points: number, elapsedMs: number): void;
41
+ /**
42
+ * Point budgets for the passes of one refinement, ascending, ending at
43
+ * `fullBudget`: a time-boxed first pass, then the full budget.
44
+ */
45
+ passBudgets(fullBudget: number): number[];
46
+ }
47
+ /** What a finished (or in-flight) pass would put on screen. */
48
+ export interface LodPassQuality {
49
+ /** Increments with every camera change; a pass belongs to one view. */
50
+ viewEpoch: number;
51
+ points: number;
52
+ /** Every node of the pass is resident. */
53
+ complete: boolean;
54
+ }
55
+ /**
56
+ * Replace what is on screen only with something better: a pass for the
57
+ * same view with more points, or a COMPLETE pass for a newer view. A newer
58
+ * view's partial pass waits, so the screen never trades a full picture for
59
+ * a half-loaded one; a stale view never replaces a newer one.
60
+ */
61
+ export declare function shouldReplacePass(current: LodPassQuality | null, candidate: LodPassQuality): boolean;
62
+ //# sourceMappingURL=pacer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pacer.d.ts","sourceRoot":"","sources":["../../src/lod/pacer.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;GAaG;AAEH,MAAM,WAAW,eAAe;IAC9B,0DAA0D;IAC1D,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,uEAAuE;IACvE,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,qEAAqE;IACrE,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,yEAAyE;IACzE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,yEAAyE;IACzE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,kEAAkE;IAClE,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,qBAAa,QAAQ;IACnB,OAAO,CAAC,IAAI,CAAS;IACrB,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAS;IAC5C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;gBAEvB,OAAO,GAAE,eAAoB;IASzC,0DAA0D;IAC1D,IAAI,WAAW,IAAI,MAAM,CAExB;IAED,wFAAwF;IACxF,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI;IAOhD;;;OAGG;IACH,WAAW,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,EAAE;CAK1C;AAED,+DAA+D;AAC/D,MAAM,WAAW,cAAc;IAC7B,uEAAuE;IACvE,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,0CAA0C;IAC1C,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,cAAc,GAAG,IAAI,EAAE,SAAS,EAAE,cAAc,GAAG,OAAO,CAKpG"}
@@ -0,0 +1,56 @@
1
+ /* This Source Code Form is subject to the terms of the Mozilla Public
2
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
3
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
+ export class LodPacer {
5
+ rate;
6
+ firstPassMs;
7
+ minFirstPassPoints;
8
+ fallAlpha;
9
+ riseAlpha;
10
+ clipRatio;
11
+ constructor(options = {}) {
12
+ this.rate = Math.max(1e-6, options.initialPointsPerMs ?? 1_000);
13
+ this.firstPassMs = Math.max(1, options.firstPassMs ?? 200);
14
+ this.minFirstPassPoints = Math.max(1, Math.floor(options.minFirstPassPoints ?? 50_000));
15
+ this.fallAlpha = options.fallAlpha ?? 0.5;
16
+ this.riseAlpha = options.riseAlpha ?? 0.1;
17
+ this.clipRatio = Math.max(1, options.clipRatio ?? 4);
18
+ }
19
+ /** Current read-rate estimate, points per millisecond. */
20
+ get pointsPerMs() {
21
+ return this.rate;
22
+ }
23
+ /** Record that `points` were read in `elapsedMs`. Uninformative samples are ignored. */
24
+ observe(points, elapsedMs) {
25
+ if (!(points > 0) || !(elapsedMs > 0) || !Number.isFinite(points) || !Number.isFinite(elapsedMs))
26
+ return;
27
+ const sample = Math.min(this.rate * this.clipRatio, Math.max(this.rate / this.clipRatio, points / elapsedMs));
28
+ const alpha = sample < this.rate ? this.fallAlpha : this.riseAlpha;
29
+ this.rate += alpha * (sample - this.rate);
30
+ }
31
+ /**
32
+ * Point budgets for the passes of one refinement, ascending, ending at
33
+ * `fullBudget`: a time-boxed first pass, then the full budget.
34
+ */
35
+ passBudgets(fullBudget) {
36
+ const full = Math.max(0, Math.floor(fullBudget));
37
+ const first = Math.max(this.minFirstPassPoints, Math.floor(this.rate * this.firstPassMs));
38
+ return first >= full ? [full] : [first, full];
39
+ }
40
+ }
41
+ /**
42
+ * Replace what is on screen only with something better: a pass for the
43
+ * same view with more points, or a COMPLETE pass for a newer view. A newer
44
+ * view's partial pass waits, so the screen never trades a full picture for
45
+ * a half-loaded one; a stale view never replaces a newer one.
46
+ */
47
+ export function shouldReplacePass(current, candidate) {
48
+ if (!current)
49
+ return true;
50
+ if (candidate.viewEpoch < current.viewEpoch)
51
+ return false;
52
+ if (candidate.viewEpoch > current.viewEpoch)
53
+ return candidate.complete;
54
+ return candidate.points > current.points;
55
+ }
56
+ //# sourceMappingURL=pacer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pacer.js","sourceRoot":"","sources":["../../src/lod/pacer.ts"],"names":[],"mappings":"AAAA;;+DAE+D;AAgC/D,MAAM,OAAO,QAAQ;IACX,IAAI,CAAS;IACJ,WAAW,CAAS;IACpB,kBAAkB,CAAS;IAC3B,SAAS,CAAS;IAClB,SAAS,CAAS;IAClB,SAAS,CAAS;IAEnC,YAAY,UAA2B,EAAE;QACvC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,OAAO,CAAC,kBAAkB,IAAI,KAAK,CAAC,CAAC;QAChE,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,WAAW,IAAI,GAAG,CAAC,CAAC;QAC3D,IAAI,CAAC,kBAAkB,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,kBAAkB,IAAI,MAAM,CAAC,CAAC,CAAC;QACxF,IAAI,CAAC,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,GAAG,CAAC;QAC1C,IAAI,CAAC,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,GAAG,CAAC;QAC1C,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,SAAS,IAAI,CAAC,CAAC,CAAC;IACvD,CAAC;IAED,0DAA0D;IAC1D,IAAI,WAAW;QACb,OAAO,IAAI,CAAC,IAAI,CAAC;IACnB,CAAC;IAED,wFAAwF;IACxF,OAAO,CAAC,MAAc,EAAE,SAAiB;QACvC,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,SAAS,GAAG,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC;YAAE,OAAO;QACzG,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC,CAAC;QAC9G,MAAM,KAAK,GAAG,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC;QACnE,IAAI,CAAC,IAAI,IAAI,KAAK,GAAG,CAAC,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC;IAC5C,CAAC;IAED;;;OAGG;IACH,WAAW,CAAC,UAAkB;QAC5B,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC;QACjD,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,kBAAkB,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC;QAC1F,OAAO,KAAK,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IAChD,CAAC;CACF;AAWD;;;;;GAKG;AACH,MAAM,UAAU,iBAAiB,CAAC,OAA8B,EAAE,SAAyB;IACzF,IAAI,CAAC,OAAO;QAAE,OAAO,IAAI,CAAC;IAC1B,IAAI,SAAS,CAAC,SAAS,GAAG,OAAO,CAAC,SAAS;QAAE,OAAO,KAAK,CAAC;IAC1D,IAAI,SAAS,CAAC,SAAS,GAAG,OAAO,CAAC,SAAS;QAAE,OAAO,SAAS,CAAC,QAAQ,CAAC;IACvE,OAAO,SAAS,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;AAC3C,CAAC"}
@@ -0,0 +1,80 @@
1
+ /**
2
+ * View-dependent level-of-detail selection over an additive point octree
3
+ * (#6869). Pure: no renderer, no I/O, no clock. Implemented from the
4
+ * technique as described in the issue (priority refinement by projected
5
+ * size, node cap, water-filled point budget), not from any other code.
6
+ *
7
+ * 1. Frustum-cull. A node outside the view is never selected, nor is any
8
+ * of its descendants.
9
+ * 2. Refine priority-first: repeatedly take the selected node with the
10
+ * largest projected screen span (bounding-sphere diameter in pixels)
11
+ * and add its visible children, while that span exceeds
12
+ * `pixelThreshold` and the selection stays within `maxNodes`. The
13
+ * octree is additive (a parent holds a coarse subsample, children add
14
+ * detail), so a parent stays selected and always precedes its children.
15
+ * 3. Share `pointBudget` across the selected nodes by water-filling: every
16
+ * node gets the same share, capped by its own point count, with what a
17
+ * small node cannot use passed on to the larger ones.
18
+ *
19
+ * Ties break by node id, so the result is independent of child order.
20
+ */
21
+ import type { PointCloudBBox } from '../types.js';
22
+ export interface LodNode {
23
+ /** Unique, stable id (the tie-breaker that makes selection deterministic). */
24
+ readonly id: string;
25
+ /** Bounds in the camera's frame. */
26
+ readonly bounds: PointCloudBBox;
27
+ readonly pointCount: number;
28
+ /** Child nodes, or `null` while this subtree's hierarchy is not loaded. */
29
+ readonly children: readonly LodNode[] | null;
30
+ }
31
+ export interface LodCamera {
32
+ /** Column-major view-projection into WebGPU clip space (z in [0, w], either direction). */
33
+ viewProj: ArrayLike<number>;
34
+ /** Eye position, same frame as the node bounds. */
35
+ position: readonly [number, number, number];
36
+ /** Viewport height in pixels. */
37
+ viewportHeight: number;
38
+ /** Projection element [1][1]: 1/tan(fovY/2), or 2/(top-bottom) when orthographic. */
39
+ projScaleY: number;
40
+ orthographic?: boolean;
41
+ }
42
+ export interface LodOptions {
43
+ pointBudget: number;
44
+ /** Refine while a node spans more than this many pixels. Default 96. */
45
+ pixelThreshold?: number;
46
+ /** Selection cap. Default `clamp(pointBudget / 128, 8, 1024)`. */
47
+ maxNodes?: number;
48
+ }
49
+ export interface LodSelectedNode {
50
+ node: LodNode;
51
+ /** Projected bounding-sphere diameter, pixels (Infinity with the eye inside). */
52
+ screenSpan: number;
53
+ /** Points this node may contribute (<= node.pointCount). */
54
+ points: number;
55
+ /** Keep every `stride`-th point: `ceil(pointCount / stride) <= points`. */
56
+ stride: number;
57
+ }
58
+ export interface LodSelection {
59
+ /** Parents before children. */
60
+ nodes: LodSelectedNode[];
61
+ /** Nodes that should refine but whose children are not loaded yet. */
62
+ needsChildren: LodNode[];
63
+ /** Sum of `points`; never above the budget. */
64
+ totalPoints: number;
65
+ /** True when `maxNodes` stopped refinement. */
66
+ capped: boolean;
67
+ }
68
+ export declare const DEFAULT_PIXEL_THRESHOLD = 96;
69
+ export declare function defaultMaxNodes(pointBudget: number): number;
70
+ /** Projected diameter in pixels of the node's bounding sphere. */
71
+ export declare function screenSpan(bounds: PointCloudBBox, camera: LodCamera): number;
72
+ export declare function selectLod(root: LodNode, camera: LodCamera, options: LodOptions): LodSelection;
73
+ /**
74
+ * Max-min fair split of `budget` over `counts`: one common level L, each
75
+ * share `min(count, L)`, with the integer remainder going one point at a
76
+ * time to the earliest uncapped entries. The result sums to
77
+ * `min(budget, sum(counts))`.
78
+ */
79
+ export declare function waterFill(counts: readonly number[], budget: number): number[];
80
+ //# sourceMappingURL=select.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"select.d.ts","sourceRoot":"","sources":["../../src/lod/select.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAGlD,MAAM,WAAW,OAAO;IACtB,8EAA8E;IAC9E,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,oCAAoC;IACpC,QAAQ,CAAC,MAAM,EAAE,cAAc,CAAC;IAChC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,2EAA2E;IAC3E,QAAQ,CAAC,QAAQ,EAAE,SAAS,OAAO,EAAE,GAAG,IAAI,CAAC;CAC9C;AAED,MAAM,WAAW,SAAS;IACxB,2FAA2F;IAC3F,QAAQ,EAAE,SAAS,CAAC,MAAM,CAAC,CAAC;IAC5B,mDAAmD;IACnD,QAAQ,EAAE,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IAC5C,iCAAiC;IACjC,cAAc,EAAE,MAAM,CAAC;IACvB,qFAAqF;IACrF,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,UAAU;IACzB,WAAW,EAAE,MAAM,CAAC;IACpB,wEAAwE;IACxE,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,kEAAkE;IAClE,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,OAAO,CAAC;IACd,iFAAiF;IACjF,UAAU,EAAE,MAAM,CAAC;IACnB,4DAA4D;IAC5D,MAAM,EAAE,MAAM,CAAC;IACf,2EAA2E;IAC3E,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,YAAY;IAC3B,+BAA+B;IAC/B,KAAK,EAAE,eAAe,EAAE,CAAC;IACzB,sEAAsE;IACtE,aAAa,EAAE,OAAO,EAAE,CAAC;IACzB,+CAA+C;IAC/C,WAAW,EAAE,MAAM,CAAC;IACpB,+CAA+C;IAC/C,MAAM,EAAE,OAAO,CAAC;CACjB;AAED,eAAO,MAAM,uBAAuB,KAAK,CAAC;AAE1C,wBAAgB,eAAe,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAE3D;AAED,kEAAkE;AAClE,wBAAgB,UAAU,CAAC,MAAM,EAAE,cAAc,EAAE,MAAM,EAAE,SAAS,GAAG,MAAM,CAa5E;AAmDD,wBAAgB,SAAS,CAAC,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,UAAU,GAAG,YAAY,CA+C7F;AAED;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAwB7E"}
@@ -0,0 +1,155 @@
1
+ /* This Source Code Form is subject to the terms of the Mozilla Public
2
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
3
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
+ import { boxIntersectsFrustum, frustumPlanes } from './frustum.js';
5
+ export const DEFAULT_PIXEL_THRESHOLD = 96;
6
+ export function defaultMaxNodes(pointBudget) {
7
+ return Math.min(1024, Math.max(8, Math.floor(pointBudget / 128)));
8
+ }
9
+ /** Projected diameter in pixels of the node's bounding sphere. */
10
+ export function screenSpan(bounds, camera) {
11
+ const dx = bounds.max[0] - bounds.min[0];
12
+ const dy = bounds.max[1] - bounds.min[1];
13
+ const dz = bounds.max[2] - bounds.min[2];
14
+ const radius = Math.hypot(dx, dy, dz) / 2;
15
+ const scale = camera.projScaleY * camera.viewportHeight;
16
+ if (camera.orthographic)
17
+ return radius * scale;
18
+ const cx = (bounds.min[0] + bounds.max[0]) / 2 - camera.position[0];
19
+ const cy = (bounds.min[1] + bounds.max[1]) / 2 - camera.position[1];
20
+ const cz = (bounds.min[2] + bounds.max[2]) / 2 - camera.position[2];
21
+ const distance = Math.hypot(cx, cy, cz);
22
+ if (distance <= radius)
23
+ return Infinity;
24
+ return (radius * scale) / distance;
25
+ }
26
+ /** Larger span first; ties by id. */
27
+ function before(a, b) {
28
+ if (a.span !== b.span)
29
+ return a.span > b.span;
30
+ return a.node.id < b.node.id;
31
+ }
32
+ class MaxHeap {
33
+ items = [];
34
+ get size() {
35
+ return this.items.length;
36
+ }
37
+ push(c) {
38
+ const items = this.items;
39
+ items.push(c);
40
+ let i = items.length - 1;
41
+ while (i > 0) {
42
+ const parent = (i - 1) >> 1;
43
+ if (!before(items[i], items[parent]))
44
+ break;
45
+ [items[i], items[parent]] = [items[parent], items[i]];
46
+ i = parent;
47
+ }
48
+ }
49
+ pop() {
50
+ const items = this.items;
51
+ const top = items[0];
52
+ const last = items.pop();
53
+ if (items.length > 0 && last) {
54
+ items[0] = last;
55
+ let i = 0;
56
+ while (true) {
57
+ const l = 2 * i + 1;
58
+ const r = l + 1;
59
+ let best = i;
60
+ if (l < items.length && before(items[l], items[best]))
61
+ best = l;
62
+ if (r < items.length && before(items[r], items[best]))
63
+ best = r;
64
+ if (best === i)
65
+ break;
66
+ [items[i], items[best]] = [items[best], items[i]];
67
+ i = best;
68
+ }
69
+ }
70
+ return top;
71
+ }
72
+ }
73
+ export function selectLod(root, camera, options) {
74
+ const budget = Math.max(0, Math.floor(options.pointBudget));
75
+ const threshold = options.pixelThreshold ?? DEFAULT_PIXEL_THRESHOLD;
76
+ const maxNodes = Math.max(1, Math.floor(options.maxNodes ?? defaultMaxNodes(budget)));
77
+ const planes = frustumPlanes(camera.viewProj);
78
+ const empty = { nodes: [], needsChildren: [], totalPoints: 0, capped: false };
79
+ if (budget === 0 || !boxIntersectsFrustum(root.bounds, planes))
80
+ return empty;
81
+ const chosen = [{ node: root, span: screenSpan(root.bounds, camera) }];
82
+ const needsChildren = [];
83
+ const heap = new MaxHeap();
84
+ heap.push(chosen[0]);
85
+ let capped = false;
86
+ while (heap.size > 0) {
87
+ const next = heap.pop();
88
+ if (!next || !(next.span > threshold))
89
+ break; // the largest is small enough: done
90
+ const children = next.node.children;
91
+ if (children === null) {
92
+ needsChildren.push(next.node);
93
+ continue;
94
+ }
95
+ const visible = children
96
+ .filter((child) => boxIntersectsFrustum(child.bounds, planes))
97
+ .map((child) => ({ node: child, span: screenSpan(child.bounds, camera) }))
98
+ .sort((a, b) => (before(a, b) ? -1 : 1));
99
+ if (chosen.length + visible.length > maxNodes) {
100
+ // Refinement is all-children-or-none, in strict priority order, so the
101
+ // selection for a smaller cap is always a prefix of a larger one's.
102
+ capped = true;
103
+ break;
104
+ }
105
+ for (const child of visible) {
106
+ chosen.push(child);
107
+ heap.push(child);
108
+ }
109
+ }
110
+ const allocation = waterFill(chosen.map((c) => c.node.pointCount), budget);
111
+ const nodes = [];
112
+ let totalPoints = 0;
113
+ chosen.forEach((c, i) => {
114
+ const points = allocation[i];
115
+ if (points <= 0)
116
+ return;
117
+ nodes.push({ node: c.node, screenSpan: c.span, points, stride: Math.ceil(c.node.pointCount / points) });
118
+ totalPoints += points;
119
+ });
120
+ return { nodes, needsChildren, totalPoints, capped };
121
+ }
122
+ /**
123
+ * Max-min fair split of `budget` over `counts`: one common level L, each
124
+ * share `min(count, L)`, with the integer remainder going one point at a
125
+ * time to the earliest uncapped entries. The result sums to
126
+ * `min(budget, sum(counts))`.
127
+ */
128
+ export function waterFill(counts, budget) {
129
+ const caps = counts.map((c) => Math.max(0, Math.floor(c)));
130
+ const total = caps.reduce((a, b) => a + b, 0);
131
+ if (total <= budget)
132
+ return caps;
133
+ const order = caps.map((c, i) => i).sort((a, b) => caps[a] - caps[b] || a - b);
134
+ const out = new Array(caps.length).fill(0);
135
+ let remaining = budget;
136
+ let open = caps.length;
137
+ let k = 0;
138
+ // Fill the smallest entries completely while they fit under the level.
139
+ while (k < order.length && caps[order[k]] * open <= remaining) {
140
+ out[order[k]] = caps[order[k]];
141
+ remaining -= caps[order[k]];
142
+ open--;
143
+ k++;
144
+ }
145
+ const level = open > 0 ? Math.floor(remaining / open) : 0;
146
+ let extra = open > 0 ? remaining - level * open : 0;
147
+ const uncapped = order.slice(k).sort((a, b) => a - b);
148
+ for (const i of uncapped) {
149
+ out[i] = level + (extra > 0 ? 1 : 0);
150
+ if (extra > 0)
151
+ extra--;
152
+ }
153
+ return out;
154
+ }
155
+ //# sourceMappingURL=select.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"select.js","sourceRoot":"","sources":["../../src/lod/select.ts"],"names":[],"mappings":"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"}
@@ -6,10 +6,11 @@
6
6
  * `Uint8Array` — the underlying ArrayBuffer is owned by the caller and
7
7
  * safe to transfer across postMessage boundaries.
8
8
  */
9
- export declare class BlobByteSource {
9
+ import type { RangeByteSource } from './types.js';
10
+ export declare class BlobByteSource implements RangeByteSource {
10
11
  private readonly blob;
11
12
  constructor(blob: Blob);
12
13
  get size(): number;
13
- read(start: number, end: number): Promise<Uint8Array>;
14
+ read(start: number, end: number, signal?: AbortSignal): Promise<Uint8Array>;
14
15
  }
15
16
  //# sourceMappingURL=blob-source.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"blob-source.d.ts","sourceRoot":"","sources":["../../src/streaming/blob-source.ts"],"names":[],"mappings":"AAIA;;;;;;;GAOG;AACH,qBAAa,cAAc;IACb,OAAO,CAAC,QAAQ,CAAC,IAAI;gBAAJ,IAAI,EAAE,IAAI;IAEvC,IAAI,IAAI,IAAI,MAAM,CAEjB;IAEK,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;CAQ5D"}
1
+ {"version":3,"file":"blob-source.d.ts","sourceRoot":"","sources":["../../src/streaming/blob-source.ts"],"names":[],"mappings":"AAIA;;;;;;;GAOG;AACH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAElD,qBAAa,cAAe,YAAW,eAAe;IACxC,OAAO,CAAC,QAAQ,CAAC,IAAI;gBAAJ,IAAI,EAAE,IAAI;IAEvC,IAAI,IAAI,IAAI,MAAM,CAEjB;IAEK,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC;CASlF"}
@@ -1,14 +1,6 @@
1
1
  /* This Source Code Form is subject to the terms of the Mozilla Public
2
2
  * License, v. 2.0. If a copy of the MPL was not distributed with this
3
3
  * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
- /**
5
- * Byte-range reader backed by a Blob.
6
- *
7
- * Works for both browser `File` objects (drag-and-drop) and `fetch()`
8
- * responses materialised via `await response.blob()`. Reads return
9
- * `Uint8Array` — the underlying ArrayBuffer is owned by the caller and
10
- * safe to transfer across postMessage boundaries.
11
- */
12
4
  export class BlobByteSource {
13
5
  blob;
14
6
  constructor(blob) {
@@ -17,7 +9,8 @@ export class BlobByteSource {
17
9
  get size() {
18
10
  return this.blob.size;
19
11
  }
20
- async read(start, end) {
12
+ async read(start, end, signal) {
13
+ signal?.throwIfAborted();
21
14
  const safeStart = Math.max(0, start);
22
15
  const safeEnd = Math.min(end, this.blob.size);
23
16
  if (safeEnd <= safeStart)