gaussian-splat-lite 1.4.2 → 1.4.3

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 (48) hide show
  1. package/CHANGELOG.md +22 -1
  2. package/bin/build-lod.js +17 -2
  3. package/bin/rad/parallel.js +7 -6
  4. package/bin/rad/splats.js +27 -10
  5. package/dist/gaussian-splat-lite.cjs +104 -70
  6. package/dist/gaussian-splat-lite.cjs.map +1 -1
  7. package/dist/gaussian-splat-lite.min.cjs +51 -51
  8. package/dist/gaussian-splat-lite.min.cjs.map +1 -1
  9. package/dist/gaussian-splat-lite.module.js +104 -70
  10. package/dist/gaussian-splat-lite.module.js.map +1 -1
  11. package/dist/gaussian-splat-lite.module.min.js +563 -544
  12. package/dist/gaussian-splat-lite.module.min.js.map +1 -1
  13. package/dist/types/data/IndexedSplats.d.cts +1 -4
  14. package/dist/types/data/IndexedSplats.d.ts +1 -4
  15. package/dist/types/data/Splats.d.cts +2 -6
  16. package/dist/types/data/Splats.d.ts +2 -6
  17. package/dist/types/data/defines.d.cts +3 -4
  18. package/dist/types/data/defines.d.ts +3 -4
  19. package/dist/types/data/splatData.d.cts +1 -1
  20. package/dist/types/data/splatData.d.ts +1 -1
  21. package/dist/types/data/splatRange.d.cts +1 -1
  22. package/dist/types/data/splatRange.d.ts +1 -1
  23. package/dist/types/loaders/morton.d.cts +6 -3
  24. package/dist/types/loaders/morton.d.ts +6 -3
  25. package/dist/types/loaders/postDecode/protocol.d.cts +1 -0
  26. package/dist/types/loaders/postDecode/protocol.d.ts +1 -0
  27. package/dist/types/loaders/rad.d.cts +5 -5
  28. package/dist/types/loaders/rad.d.ts +5 -5
  29. package/dist/types/loaders/stream/rad-stream/RadStreamScheduler.d.cts +0 -2
  30. package/dist/types/loaders/stream/rad-stream/RadStreamScheduler.d.ts +0 -2
  31. package/dist/types/loaders/stream/sog-stream/SogStreamLoader.d.cts +1 -1
  32. package/dist/types/loaders/stream/sog-stream/SogStreamLoader.d.ts +1 -1
  33. package/dist/types/loaders/stream/sog-stream/SogStreamScheduler.d.cts +16 -2
  34. package/dist/types/loaders/stream/sog-stream/SogStreamScheduler.d.ts +16 -2
  35. package/dist/types/loaders/stream/sog-stream/sogLod.d.cts +8 -9
  36. package/dist/types/loaders/stream/sog-stream/sogLod.d.ts +8 -9
  37. package/dist/types/loaders/stream/sog-stream/sogVisibility.d.cts +13 -7
  38. package/dist/types/loaders/stream/sog-stream/sogVisibility.d.ts +13 -7
  39. package/dist/types/loaders/stream/streamOptions.d.cts +1 -1
  40. package/dist/types/loaders/stream/streamOptions.d.ts +1 -1
  41. package/dist/types/scene/SplatMesh.d.cts +0 -2
  42. package/dist/types/scene/SplatMesh.d.ts +0 -2
  43. package/docs/BuildRad.md +1 -0
  44. package/docs/RadStreamScheduler.md +4 -4
  45. package/docs/SogStreamScheduler.md +14 -4
  46. package/docs/SplatMesh.md +2 -2
  47. package/docs/Splats.md +1 -3
  48. package/package.json +1 -1
@@ -107,7 +107,6 @@ Unused detail is released after `cooldownMs`, including while hidden, and loads
107
107
  | `setResolutionFromRenderer(camera, renderer)` | Set a registered camera's size from `renderer.getSize()` |
108
108
  | `update()` | Advance detail selection, loading, and fades. Call it before every render; it throws if no camera is registered |
109
109
  | `getBoundingBox()` | Approximate box around the scene, in the group's coordinates; empty until the first data loads |
110
- | `getGlobalIndex(mesh, renderedIndex)` | Convert a picking hit into a node index that stays the same for the whole RAD file |
111
110
  | `stats` | Visible Splats, loading progress, and estimated CPU/GPU cache sizes (`residentCpuBytes` / `residentGpuBytes`) |
112
111
  | `dispose()` | Stop loading and release the scene. Pending `initialized` and `firstRenderable` promises reject with `AbortError` |
113
112
 
@@ -117,13 +116,14 @@ Request a redraw from `onChange`, and keep calling `update()` on every animation
117
116
 
118
117
  ### Picking
119
118
 
120
- Hits from a streamed scene refer to the detail that is currently shown. Use `getGlobalIndex()`, or the hit's [`sourceIndex`](SplatMesh.md#raycasting), for an ID that does not change:
119
+ Hits from a streamed scene refer to the detail that is currently shown. Read the hit Splat before the streaming selection updates, since its index can change:
121
120
 
122
121
  ```js
123
122
  const hits = raycaster.intersectObject(streaming.group, true);
124
123
  if (hits.length && hits[0].index !== undefined) {
125
- const nodeIndex = streaming.getGlobalIndex(hits[0].object, hits[0].index);
126
- console.log(nodeIndex, hits[0].point);
124
+ const hit = hits[0];
125
+ const splat = hit.object.splats.getSplat(hit.index);
126
+ console.log(splat, hit.point);
127
127
  }
128
128
  ```
129
129
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  [Back to documentation](../README.md#documentation)
4
4
 
5
- Shows large SOG `lod-meta.json` scenes by loading only the detail the camera needs, and updating it as the camera moves. It supports version 1 and older unversioned indexes, on WebGPU and WebGL2. For an ordinary `.sog` file or `meta.json`, use [SplatMesh](SplatMesh.md).
5
+ Shows large SOG `lod-meta.json` scenes with camera-driven detail, keeping coarser surroundings ready as the camera turns. It supports version 1 and older unversioned indexes, on WebGPU and WebGL2. For an ordinary `.sog` file or `meta.json`, use [SplatMesh](SplatMesh.md).
6
6
 
7
7
  ```js
8
8
  import { SogStreamScheduler } from "gaussian-splat-lite";
@@ -34,11 +34,15 @@ The three steps that matter:
34
34
  2. Register the camera.
35
35
  3. Call `streaming.update()` before every render.
36
36
 
37
- Streamed models support [SDF edits](SplatEdit.md) and [picking](SplatMesh.md#raycasting). Their data is read-only. For a Splat's original ID, use the picking hit's [`sourceIndex`](SplatMesh.md#raycasting).
37
+ Streamed models support [SDF edits](SplatEdit.md) and [picking](SplatMesh.md#raycasting). Their data is read-only. Read a hit with `hit.object.splats.getSplat(hit.index)` before the streaming selection updates.
38
38
 
39
39
  ## Cameras
40
40
 
41
- Detail depends on distance from the camera, so cameras need no resolution. Register several cameras to load detail for all of them; each part of the scene follows the nearest camera that sees it.
41
+ Detail depends on distance and camera direction, so cameras need no resolution. Regions outside the view remain part of the same budget, with less detail behind the camera. This keeps surrounding content ready for turns, at the cost of some detail in the current view. Register several cameras to load detail for all of them; each region follows the camera requesting the finest detail.
42
+
43
+ Oversized region bounds are reduced toward the scene's median region size when measuring LOD distance. This prevents large background regions from receiving excessive detail just because an edge is close to the camera. Geometry, rendering bounds, and picking are unaffected by this distance correction.
44
+
45
+ ### WebXR
42
46
 
43
47
  In WebXR, register `renderer.xr.getCamera()` in place of your camera, as shown for [RadStreamScheduler](RadStreamScheduler.md#webxr). Detail is chosen for each eye.
44
48
 
@@ -52,6 +56,8 @@ In WebXR, register `renderer.xr.getCamera()` in place of your camera, as shown f
52
56
  | `splatBudgetMode` | `"target"` | `"target"` adjusts the distance bands to fill the budget. `"limit"` uses the configured distance bands and only reduces detail when they exceed the budget |
53
57
  | `lodBaseDistance` | `100` | Base LOD distance in world units for `"limit"` mode, compensated for the camera's field of view. Higher values retain finer detail farther away. Must be finite and positive |
54
58
  | `lodMultiplier` | `2` | Distance multiplier between successive LOD levels in both modes. Must be finite and at least `1` |
59
+ | `lodBehindPenalty` | `4` | Effective distance multiplier directly behind a camera, increasing smoothly from `1` at its sides. With the default LOD multiplier, `4` shifts rear detail by two distance bands. `1` disables directional bias. Must be finite and at least `1` |
60
+ | `lodDistanceShrink` | `0.75` | Fraction of a region's excess half-size above the scene median removed when measuring distance, independently on each axis. Higher values reduce detail in oversized regions; `0` disables the correction. Must be finite and between `0` and `1` |
55
61
  | `fadeDurationMs` | `200` | Duration of the fade when the scene first appears and when detail changes; `0` switches instantly |
56
62
  | `cooldownMs` | `2000` | How long detail that is no longer shown stays in memory, ready for reuse; `0` releases it at once |
57
63
  | `maxConcurrentLoads` | `4` | Maximum number of loads in progress at the same time |
@@ -70,6 +76,8 @@ In WebXR, register `renderer.xr.getCamera()` in place of your camera, as shown f
70
76
  | `splatBudgetMode` | Switch between `"target"` and `"limit"` without reloading |
71
77
  | `lodBaseDistance` | Change the base LOD distance in `"limit"` mode without reloading |
72
78
  | `lodMultiplier` | Change the distance spacing between LOD levels in both modes without reloading |
79
+ | `lodBehindPenalty` | Change how strongly detail behind the camera is reduced, in both modes, without reloading |
80
+ | `lodDistanceShrink` | Change the distance correction for oversized regions, in both modes, without reloading |
73
81
  | `initialized` | Resolves when the index is loaded; rejects for invalid input |
74
82
  | `firstRenderable` | Resolves when the first data is on screen, or the scene is empty; rejects if the first data cannot be loaded. Keep calling `update()` while you wait |
75
83
  | `setCamera(camera)` / `deleteCamera(camera)` | Add or remove a camera that chooses detail. `hasCamera(camera)` and `cameras` report the registered ones |
@@ -88,4 +96,6 @@ Temporary download failures are retried automatically, waiting longer after each
88
96
 
89
97
  Invalid data, out-of-memory errors, and other HTTP errors are reported to `onError` and are not retried. Parts of the scene that are already on screen stay visible when loading more detail fails.
90
98
 
91
- If the scheduler can no longer choose detail after an internal failure, it calls `onError` and disposes itself. Create a new scheduler to try again.
99
+ `firstRenderable` waits for the initial detail selection before deciding that all needed loads have failed permanently. An environment failure alone does not reject it while scene selection is pending.
100
+
101
+ If detail selection fails, the scheduler calls `onError`, stops loading, and retains the last displayed coverage while its fades finish. Create a new scheduler to try again, and call `dispose()` before discarding the old one.
package/docs/SplatMesh.md CHANGED
@@ -127,9 +127,9 @@ if (intersections.length > 0) {
127
127
  ```
128
128
 
129
129
  - The model needs `raycastable: true`, the default. Picking may return nothing while the model is still being set up.
130
- - Each hit has an `index`, for reading the Splat from the current data, and a `sourceIndex`, its ID in the original file (`SplatIntersection` in TypeScript).
130
+ - Each hit contains `distance`, `point`, `object`, and `index` (`SplatIntersection` in TypeScript). Read the hit Splat with `hit.object.splats.getSplat(hit.index)`.
131
131
  - Values of `minRaycastOpacity` below `0.01` have limited effect: areas that transparent may not be pickable.
132
- - Streamed models can be picked. Hits ignore their display fades, and an `index` can change as the shown detail changes. For RAD, `sourceIndex` is the node index within the whole file; for streamed SOG, it is the index within the chunk file the hit Splat was loaded from.
132
+ - Streamed models can be picked. Hits ignore their display fades. An `index` belongs to the hit object's current data and can change as the shown detail changes; read the Splat before the streaming selection updates.
133
133
 
134
134
  ## Scene integration
135
135
 
package/docs/Splats.md CHANGED
@@ -10,7 +10,6 @@ Wait for loading to finish before reading:
10
10
  await splat.initialized;
11
11
  const data = splat.splats;
12
12
  const item = data.getSplat(0);
13
- const sourceIndex = data.getSourceIndex(0);
14
13
  ```
15
14
 
16
15
  ## Options
@@ -39,7 +38,6 @@ Choose at most one of `url`, `file`, or `fileBytes`; combining them throws.
39
38
  | `getNumSplats()` / `getNumSh()` | Splat count, and the level of view-dependent color (spherical harmonics degree) the model has |
40
39
  | `getByteLength()` | Memory used by the data, in bytes |
41
40
  | `getSplat(index, includeSh?)` | Read one Splat; pass `false` to skip its view-dependent color |
42
- | `getSourceIndex(index)` | The Splat's ID in the original file |
43
41
  | `forEachCenter(callback)` | Visit only the center of every Splat, for example to build a spatial index |
44
42
  | `forEachSplat(callback)` | Visit every Splat |
45
43
  | `dispose()` | Cancel loading and release the data |
@@ -48,7 +46,7 @@ Calling `initialize()` again or `dispose()` cancels a load still in progress; it
48
46
 
49
47
  ## Data rules
50
48
 
51
- - **Indices are not file order.** Splats are reordered while loading. Use `getSourceIndex(index)`, or a picking hit's `sourceIndex`, to get the ID from the original file. Passing existing `Splats` to a mesh keeps their order.
49
+ - **Indices address the current data.** Splats are reordered while loading, so indices may differ from file order. Passing existing `Splats` to a mesh keeps their order. Streamed indices can change when the visible detail changes.
52
50
  - **Reads return copies.** `getSplat()` returns new `center`, `scales`, `quaternion`, `opacity`, `color`, and `sh` values on each call; changing them does not change the model. `sh` holds 0, 3, 8, 15, or 24 RGB coefficients, depending on the model's degree (SH0–SH4).
53
51
  - **`forEachSplat()` reuses its objects.** The same objects are passed for every Splat, so clone anything you want to keep after the callback returns.
54
52
  - **Streamed data is read-only.** Data from [RadStreamScheduler](RadStreamScheduler.md) or [SogStreamScheduler](SogStreamScheduler.md) cannot be reinitialized.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gaussian-splat-lite",
3
- "version": "1.4.2",
3
+ "version": "1.4.3",
4
4
  "description": "Three.js Gaussian Splatting renderer with WebGPU/WebGL2, GPU sorting, streaming LOD, and high-precision GIS/ECEF support. Supports PLY, SPZ, SOG and RAD.",
5
5
  "author": "William Liu <lyz15972107087@gmail.com>",
6
6
  "type": "module",