@cesium/engine 26.3.0 → 26.3.1-wasm.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.
- package/Build/ThirdParty/Workers/zip-web-worker.js +504 -535
- package/Build/Workers/chunk-2P3WKV6V.js +290 -0
- package/Build/Workers/{chunk-MUW4DJV7.js → chunk-2U5272QU.js} +17 -17
- package/Build/Workers/{chunk-7WXBTNRV.js → chunk-4KCOC6OZ.js} +8 -10
- package/Build/Workers/{chunk-GS7RY2DH.js → chunk-5FULJNWY.js} +11 -13
- package/Build/Workers/{chunk-2PWVICP6.js → chunk-65ZF23AQ.js} +1 -1
- package/Build/Workers/{chunk-SEJIXZZ4.js → chunk-6D5534B7.js} +10 -12
- package/Build/Workers/{chunk-MDDKCLMF.js → chunk-6GFMBHBD.js} +19 -19
- package/Build/Workers/{chunk-PKZA44LH.js → chunk-6VRGQF3D.js} +4 -4
- package/Build/Workers/{chunk-JBJ6BRIM.js → chunk-6XUIECFB.js} +4 -6
- package/Build/Workers/{chunk-DKSANM4A.js → chunk-7KWUH6RK.js} +14 -14
- package/Build/Workers/{chunk-6BSNYZZG.js → chunk-7ZBJRQQT.js} +7 -7
- package/Build/Workers/{chunk-XRZCS3HE.js → chunk-AEHANE5A.js} +991 -5612
- package/Build/Workers/chunk-AUU74SIZ.js +2420 -0
- package/Build/Workers/{chunk-2YY724ZX.js → chunk-B6V5NMIE.js} +13 -11
- package/Build/Workers/{chunk-5JCZHJUU.js → chunk-BRQ52ASU.js} +15 -17
- package/Build/Workers/{chunk-Z2DW5NM2.js → chunk-FVLSQBPH.js} +7 -14
- package/Build/Workers/{chunk-L73K5UPP.js → chunk-IFKM2GZR.js} +12 -12
- package/Build/Workers/{chunk-F34TJJLA.js → chunk-KF6OEWVT.js} +17 -17
- package/Build/Workers/{chunk-JL4NWWQY.js → chunk-KOAXSU77.js} +5 -7
- package/Build/Workers/{chunk-CKK6CUXK.js → chunk-KRVYCMGN.js} +6 -6
- package/Build/Workers/{chunk-KBGAHN5R.js → chunk-LTZRLNQP.js} +1 -1
- package/Build/Workers/{chunk-CQ4TZXAT.js → chunk-M7WEAGWT.js} +8 -8
- package/Build/Workers/{chunk-A7SMPV6B.js → chunk-MJTLGN63.js} +14 -14
- package/Build/Workers/{chunk-DZK34ZVD.js → chunk-MUNZ77KV.js} +1 -1
- package/Build/Workers/{chunk-X27HKF5E.js → chunk-NC5BUJEF.js} +2 -2
- package/Build/Workers/chunk-NYKURYFR.js +2131 -0
- package/Build/Workers/{chunk-5KG7KDDW.js → chunk-NZAQG57U.js} +7 -7
- package/Build/Workers/{chunk-JKTWW7IO.js → chunk-O5GUOP2G.js} +5 -7
- package/Build/Workers/{chunk-6R6SGKYN.js → chunk-OQUOLQTN.js} +8 -10
- package/Build/Workers/chunk-OUG5JB2K.js +46 -0
- package/Build/Workers/{chunk-HDD3RFLT.js → chunk-P4SDLSGF.js} +13 -6
- package/Build/Workers/{chunk-M6W46OAP.js → chunk-P6PC2OIM.js} +7 -7
- package/Build/Workers/{chunk-XSIUYAT6.js → chunk-PPRK3XQU.js} +31 -35
- package/Build/Workers/{chunk-4LRFYRBX.js → chunk-QGTYLWOT.js} +2 -2
- package/Build/Workers/{chunk-COKOYTRS.js → chunk-QHTLIQUH.js} +5 -7
- package/Build/Workers/{chunk-N5YK44FS.js → chunk-ROHWZQZ5.js} +5 -5
- package/Build/Workers/{chunk-XBY3354M.js → chunk-SNUWISJO.js} +6 -8
- package/Build/Workers/{chunk-EDETO6NY.js → chunk-T67YY3KP.js} +4 -2
- package/Build/Workers/{chunk-4DMAXPKB.js → chunk-TF5473GK.js} +13 -13
- package/Build/Workers/{chunk-B7Q2WF6Q.js → chunk-THHFTMAL.js} +4 -6
- package/Build/Workers/{chunk-SL2HCFYW.js → chunk-UFCZ62WM.js} +15 -13
- package/Build/Workers/{chunk-NZQUP52G.js → chunk-UV2YC2Q5.js} +11 -11
- package/Build/Workers/{chunk-E7G32DWL.js → chunk-V4ICCWYA.js} +1 -1
- package/Build/Workers/{chunk-75BC2IHI.js → chunk-VC6XXI2Z.js} +9 -9
- package/Build/Workers/{chunk-JMUUAW4X.js → chunk-VXJ6P4UI.js} +10 -10
- package/Build/Workers/{chunk-QTAEVUED.js → chunk-W2BKP7G7.js} +15 -17
- package/Build/Workers/{chunk-VRECSMG3.js → chunk-WMVGNBSH.js} +2 -2
- package/Build/Workers/{chunk-7SESBH2I.js → chunk-XFZMQZSZ.js} +4 -4
- package/Build/Workers/{chunk-Q2JS5LCB.js → chunk-XJ532R6R.js} +20 -20
- package/Build/Workers/{chunk-SLHK3KAR.js → chunk-YJNU4SM4.js} +5 -5
- package/Build/Workers/{chunk-LL2SGJYH.js → chunk-YJRDTEHQ.js} +8 -8
- package/Build/Workers/chunk-YUICDZKO.js +2660 -0
- package/Build/Workers/{chunk-ATSXKJ3L.js → chunk-Z3DEVGJV.js} +7 -7
- package/Build/Workers/{chunk-6V2KDEHL.js → chunk-ZECGI7UZ.js} +4 -4
- package/Build/Workers/{chunk-LYJUL4XQ.js → chunk-ZFLPVPUJ.js} +6 -8
- package/Build/Workers/{chunk-BNDSDQ7D.js → chunk-ZIM5H2DB.js} +11 -11
- package/Build/Workers/{chunk-KEWK6VZL.js → chunk-ZSQMGGSB.js} +14 -16
- package/Build/Workers/{chunk-2DKJSPYF.js → chunk-ZWYRGMBK.js} +16 -18
- package/Build/Workers/{chunk-UZY5XRL2.js → chunk-ZY733NZA.js} +1 -1
- package/Build/Workers/combineGeometry.js +24 -24
- package/Build/Workers/createBoxGeometry.js +18 -18
- package/Build/Workers/createBoxOutlineGeometry.js +20 -19
- package/Build/Workers/createCircleGeometry.js +28 -27
- package/Build/Workers/createCircleOutlineGeometry.js +21 -20
- package/Build/Workers/createCoplanarPolygonGeometry.js +34 -34
- package/Build/Workers/createCoplanarPolygonOutlineGeometry.js +33 -32
- package/Build/Workers/createCorridorGeometry.js +31 -31
- package/Build/Workers/createCorridorOutlineGeometry.js +30 -30
- package/Build/Workers/createCylinderGeometry.js +20 -20
- package/Build/Workers/createCylinderOutlineGeometry.js +22 -21
- package/Build/Workers/createEllipseGeometry.js +26 -26
- package/Build/Workers/createEllipseOutlineGeometry.js +19 -19
- package/Build/Workers/createEllipsoidGeometry.js +19 -19
- package/Build/Workers/createEllipsoidOutlineGeometry.js +18 -18
- package/Build/Workers/createFrustumGeometry.js +18 -18
- package/Build/Workers/createFrustumOutlineGeometry.js +18 -18
- package/Build/Workers/createGeometry.js +27 -26
- package/Build/Workers/createGroundPolylineGeometry.js +27 -26
- package/Build/Workers/createPlaneGeometry.js +18 -17
- package/Build/Workers/createPlaneOutlineGeometry.js +15 -15
- package/Build/Workers/createPolygonGeometry.js +35 -35
- package/Build/Workers/createPolygonOutlineGeometry.js +34 -34
- package/Build/Workers/createPolylineGeometry.js +28 -29
- package/Build/Workers/createPolylineVolumeGeometry.js +34 -35
- package/Build/Workers/createPolylineVolumeOutlineGeometry.js +30 -31
- package/Build/Workers/createRectangleGeometry.js +30 -30
- package/Build/Workers/createRectangleOutlineGeometry.js +23 -24
- package/Build/Workers/createSimplePolylineGeometry.js +26 -27
- package/Build/Workers/createSphereGeometry.js +19 -19
- package/Build/Workers/createSphereOutlineGeometry.js +18 -18
- package/Build/Workers/createTaskProcessorWorker.js +3 -3
- package/Build/Workers/createVectorTileClampedPolylines.js +17 -16
- package/Build/Workers/createVectorTileGeometries.js +24 -24
- package/Build/Workers/createVectorTilePoints.js +13 -13
- package/Build/Workers/createVectorTilePolygons.js +22 -22
- package/Build/Workers/createVectorTilePolylines.js +17 -16
- package/Build/Workers/createVerticesFromCesium3DTilesTerrain.js +36 -26
- package/Build/Workers/createVerticesFromGoogleEarthEnterpriseBuffer.js +24 -24
- package/Build/Workers/createVerticesFromHeightmap.js +24 -25
- package/Build/Workers/createVerticesFromQuantizedTerrainMesh.js +20 -20
- package/Build/Workers/createWallGeometry.js +27 -28
- package/Build/Workers/createWallOutlineGeometry.js +26 -27
- package/Build/Workers/decodeDraco.js +16 -12
- package/Build/Workers/decodeGoogleEarthEnterprisePacket.js +336 -337
- package/Build/Workers/decodeI3S.js +17 -12
- package/Build/Workers/{chunk-GLHDTTTO.js → decodeMeshopt.js} +23 -29
- package/Build/Workers/decodeSpz.js +1960 -0
- package/Build/Workers/gaussianSplatSorter.js +13 -6
- package/Build/Workers/gaussianSplatTextureGenerator.js +13 -6
- package/Build/Workers/incrementallyBuildTerrainPicker.js +9 -10
- package/Build/Workers/transcodeKTX2.js +26 -12
- package/Build/Workers/transferTypedArrayTest.js +1 -1
- package/Build/Workers/upsampleQuantizedTerrainMesh.js +24 -24
- package/Build/Workers/upsampleVerticesFromCesium3DTilesTerrain.js +25 -25
- package/Source/Core/Cesium3DTilesTerrainData.js +11 -1
- package/Source/Core/Cesium3DTilesTerrainGeometryProcessor.js +33 -23
- package/Source/Core/KTX2Transcoder.js +99 -5
- package/Source/Core/Resource.js +2 -0
- package/Source/Core/TaskProcessor.js +249 -129
- package/Source/Core/TrustedServers.js +34 -1
- package/Source/Core/WebAssemblyWorkerInitializer.js +125 -0
- package/Source/Core/fetchWebAssemblyBinary.js +52 -0
- package/Source/Scene/GaussianSplatPrimitive.js +153 -66
- package/Source/Scene/GltfBufferViewLoader.js +25 -13
- package/Source/Scene/GltfSpzLoader.js +5 -4
- package/Source/Scene/SpzDecoder.js +106 -0
- package/Source/ThirdParty/Workers/zip-web-worker.js +1 -1
- package/Source/ThirdParty/zip-module.wasm +0 -0
- package/Source/Workers/createTaskProcessorWorker.js +2 -0
- package/Source/Workers/createVerticesFromCesium3DTilesTerrain.js +13 -1
- package/Source/Workers/decodeDraco.js +7 -3
- package/Source/Workers/decodeI3S.js +7 -3
- package/Source/Workers/decodeMeshopt.js +21 -0
- package/Source/Workers/decodeSpz.js +20 -0
- package/Source/Workers/gaussianSplatSorter.js +7 -3
- package/Source/Workers/gaussianSplatTextureGenerator.js +7 -3
- package/Source/Workers/transcodeKTX2.js +22 -5
- package/index.d.ts +93 -0
- package/index.js +4 -1
- package/package.json +1 -1
- package/Build/Workers/chunk-B4AVL7VI.js +0 -82
- package/Build/Workers/chunk-HDPNFEPP.js +0 -3820
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import defined from "./defined.js";
|
|
2
|
+
import Resource from "./Resource.js";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Fetches a WebAssembly binary when a configuration provides its URL and does not already
|
|
6
|
+
* contain the binary.
|
|
7
|
+
*
|
|
8
|
+
* <code>TaskProcessor</code> posts the URL of the binary rather than its bytes, so that the
|
|
9
|
+
* document neither fetches nor compiles WebAssembly. Worker implementations call this function
|
|
10
|
+
* to obtain the bytes and pass them to an Emscripten module factory.
|
|
11
|
+
*
|
|
12
|
+
* The input configuration is not changed. If the configuration already carries
|
|
13
|
+
* <code>wasmBinary</code>, or has no <code>wasmBinaryFile</code>, this function returns undefined.
|
|
14
|
+
*
|
|
15
|
+
* @function fetchWebAssemblyBinary
|
|
16
|
+
*
|
|
17
|
+
* @param {WebAssemblyConfig} webAssemblyConfig The configuration posted by {@link TaskProcessor#initWebAssemblyModule}.
|
|
18
|
+
* @returns {Promise<ArrayBuffer|undefined>} A promise that resolves to the fetched binary, or undefined when no fetch is needed.
|
|
19
|
+
*
|
|
20
|
+
* @private
|
|
21
|
+
* @see TaskProcessor#initWebAssemblyModule
|
|
22
|
+
* @see createTaskProcessorWorker
|
|
23
|
+
*/
|
|
24
|
+
async function fetchWebAssemblyBinary(webAssemblyConfig) {
|
|
25
|
+
if (
|
|
26
|
+
!defined(webAssemblyConfig.wasmBinaryFile) ||
|
|
27
|
+
defined(webAssemblyConfig.wasmBinary)
|
|
28
|
+
) {
|
|
29
|
+
return undefined;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
return Resource.fetchArrayBuffer({
|
|
33
|
+
url: webAssemblyConfig.wasmBinaryFile,
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* The WebAssembly configuration posted to a worker by
|
|
39
|
+
* {@link TaskProcessor#initWebAssemblyModule}, as the first message that worker receives.
|
|
40
|
+
*
|
|
41
|
+
* @typedef {object} WebAssemblyConfig
|
|
42
|
+
*
|
|
43
|
+
* @property {string} [wasmBinaryFile] The absolute url of the WebAssembly binary. Undefined
|
|
44
|
+
* when the browser does not support WebAssembly and a fallback module is used instead.
|
|
45
|
+
* @property {string} [modulePath] The absolute URL of the JavaScript wrapper module, or the
|
|
46
|
+
* fallback module when the browser does not support WebAssembly.
|
|
47
|
+
* @property {ArrayBuffer} [wasmBinary] The binary contents, when they are already available.
|
|
48
|
+
*
|
|
49
|
+
* @private
|
|
50
|
+
*/
|
|
51
|
+
|
|
52
|
+
export default fetchWebAssemblyBinary;
|
|
@@ -35,6 +35,7 @@ import SplitDirection from "./SplitDirection.js";
|
|
|
35
35
|
import destroyObject from "../Core/destroyObject.js";
|
|
36
36
|
import ContextLimits from "../Renderer/ContextLimits.js";
|
|
37
37
|
import Transforms from "../Core/Transforms.js";
|
|
38
|
+
import getTimestamp from "../Core/getTimestamp.js";
|
|
38
39
|
|
|
39
40
|
const scratchMatrix4A = new Matrix4();
|
|
40
41
|
const scratchMatrix4C = new Matrix4();
|
|
@@ -144,12 +145,114 @@ const SnapshotState = {
|
|
|
144
145
|
* @private
|
|
145
146
|
*/
|
|
146
147
|
|
|
147
|
-
//
|
|
148
|
-
|
|
149
|
-
//
|
|
150
|
-
//
|
|
151
|
-
//
|
|
152
|
-
|
|
148
|
+
// A snapshot rebuild re-aggregates every selected tile and re-uploads the
|
|
149
|
+
// splat textures. Each rebuild is a burst of main-thread and GPU work, so the
|
|
150
|
+
// scheduler waits for the selected tile set to settle before starting one.
|
|
151
|
+
//
|
|
152
|
+
// Both values below were tuned by hand on one dev machine. They have not been
|
|
153
|
+
// measured across hardware or network speeds (coming shortly).
|
|
154
|
+
|
|
155
|
+
// How long the selected tile set must stay unchanged, with no tiles decoding
|
|
156
|
+
// or downloading, before a rebuild may start.
|
|
157
|
+
const DEFAULT_SNAPSHOT_DEBOUNCE_MILLISECONDS = 500;
|
|
158
|
+
|
|
159
|
+
// Upper bound on how long a pending rebuild can wait while the selection keeps
|
|
160
|
+
// changing. Once passed, a rebuild is forced unless a committed snapshot
|
|
161
|
+
// already covers most of the selected tiles (see the overlap check in
|
|
162
|
+
// SnapshotRebuildScheduler.update).
|
|
163
|
+
const DEFAULT_MAX_SNAPSHOT_WAIT_MILLISECONDS = 2000;
|
|
164
|
+
|
|
165
|
+
class SnapshotRebuildScheduler {
|
|
166
|
+
constructor() {
|
|
167
|
+
this._selectedTileSet = new Set();
|
|
168
|
+
this._selectionChangedTime = undefined;
|
|
169
|
+
this._pendingSince = undefined;
|
|
170
|
+
this._lastRebuildTileSet = undefined;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
get isPending() {
|
|
174
|
+
return defined(this._pendingSince);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
hasSelectedTile(tile) {
|
|
178
|
+
return this._selectedTileSet.has(tile);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
update(
|
|
182
|
+
timestamp,
|
|
183
|
+
{
|
|
184
|
+
selectedTiles,
|
|
185
|
+
rebuildRequested,
|
|
186
|
+
isBootstrap,
|
|
187
|
+
tilesLoaded,
|
|
188
|
+
tilesInFlight = false,
|
|
189
|
+
hasCommittedSnapshot = false,
|
|
190
|
+
},
|
|
191
|
+
) {
|
|
192
|
+
if (selectedTiles.length === 0) {
|
|
193
|
+
this.clear();
|
|
194
|
+
return false;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
const selectedTilesChanged = haveSelectedTilesChanged(
|
|
198
|
+
this._selectedTileSet,
|
|
199
|
+
selectedTiles,
|
|
200
|
+
);
|
|
201
|
+
if (selectedTilesChanged) {
|
|
202
|
+
this._selectedTileSet = new Set(selectedTiles);
|
|
203
|
+
this._selectionChangedTime = timestamp;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
if (
|
|
207
|
+
(selectedTilesChanged || rebuildRequested || isBootstrap) &&
|
|
208
|
+
!this.isPending
|
|
209
|
+
) {
|
|
210
|
+
this._pendingSince = timestamp;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
if (!this.isPending) {
|
|
214
|
+
return false;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
const selectionIsStable =
|
|
218
|
+
!tilesInFlight &&
|
|
219
|
+
defined(this._selectionChangedTime) &&
|
|
220
|
+
timestamp - this._selectionChangedTime >=
|
|
221
|
+
DEFAULT_SNAPSHOT_DEBOUNCE_MILLISECONDS;
|
|
222
|
+
|
|
223
|
+
let tileOverlap = 0;
|
|
224
|
+
if (defined(this._lastRebuildTileSet)) {
|
|
225
|
+
for (const tile of this._selectedTileSet) {
|
|
226
|
+
if (this._lastRebuildTileSet.has(tile)) {
|
|
227
|
+
tileOverlap++;
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
tileOverlap /= this._selectedTileSet.size;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
const deadlineReached =
|
|
234
|
+
timestamp - this._pendingSince >=
|
|
235
|
+
DEFAULT_MAX_SNAPSHOT_WAIT_MILLISECONDS &&
|
|
236
|
+
// If the committed snapshot still covers at least half of the selected
|
|
237
|
+
// tiles, the stale view is close enough to keep showing. Skip the forced
|
|
238
|
+
// rebuild and wait for the selection to settle or for tilesLoaded.
|
|
239
|
+
(!hasCommittedSnapshot || tileOverlap < 0.5);
|
|
240
|
+
|
|
241
|
+
return isBootstrap || tilesLoaded || selectionIsStable || deadlineReached;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
markRebuildStarted() {
|
|
245
|
+
this._lastRebuildTileSet = new Set(this._selectedTileSet);
|
|
246
|
+
this._pendingSince = undefined;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
clear() {
|
|
250
|
+
this._selectedTileSet.clear();
|
|
251
|
+
this._selectionChangedTime = undefined;
|
|
252
|
+
this._pendingSince = undefined;
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
|
|
153
256
|
// Minimum delay between steady re-sort requests once the camera is moving.
|
|
154
257
|
const DEFAULT_SORT_MIN_FRAME_INTERVAL = 3;
|
|
155
258
|
// ~0.5 degree camera direction change threshold before triggering steady re-sort.
|
|
@@ -236,23 +339,18 @@ function markSteadySortStart(primitive, frameState) {
|
|
|
236
339
|
}
|
|
237
340
|
|
|
238
341
|
/**
|
|
239
|
-
*
|
|
240
|
-
*
|
|
241
|
-
*
|
|
242
|
-
*
|
|
243
|
-
* @param {GaussianSplatPrimitive} primitive The splat primitive.
|
|
244
|
-
* @param {Cesium3DTile[]} selectedTiles The tiles selected this frame.
|
|
245
|
-
* @returns {boolean} {@code true} if the tile set has changed.
|
|
342
|
+
* @param {Set<Cesium3DTile>} previousTiles The prior selected tile set.
|
|
343
|
+
* @param {Cesium3DTile[]} selectedTiles The current selected tiles.
|
|
344
|
+
* @returns {boolean} Whether the tile set changed.
|
|
246
345
|
* @private
|
|
247
346
|
*/
|
|
248
|
-
function haveSelectedTilesChanged(
|
|
249
|
-
|
|
250
|
-
if (!defined(prevSet) || prevSet.size !== selectedTiles.length) {
|
|
347
|
+
function haveSelectedTilesChanged(previousTiles, selectedTiles) {
|
|
348
|
+
if (previousTiles.size !== selectedTiles.length) {
|
|
251
349
|
return true;
|
|
252
350
|
}
|
|
253
351
|
|
|
254
352
|
for (let i = 0; i < selectedTiles.length; i++) {
|
|
255
|
-
if (!
|
|
353
|
+
if (!previousTiles.has(selectedTiles[i])) {
|
|
256
354
|
return true;
|
|
257
355
|
}
|
|
258
356
|
}
|
|
@@ -868,9 +966,7 @@ function GaussianSplatPrimitive(options) {
|
|
|
868
966
|
* @private
|
|
869
967
|
*/
|
|
870
968
|
this._scratchAggregateShBuffer = undefined;
|
|
871
|
-
this.
|
|
872
|
-
this._needsSnapshotRebuild = false;
|
|
873
|
-
this._snapshotRebuildStallFrames = 0;
|
|
969
|
+
this._snapshotRebuildScheduler = new SnapshotRebuildScheduler();
|
|
874
970
|
|
|
875
971
|
/**
|
|
876
972
|
* The previous view matrix used to determine if the primitive needs to be updated.
|
|
@@ -957,7 +1053,6 @@ function GaussianSplatPrimitive(options) {
|
|
|
957
1053
|
* @private
|
|
958
1054
|
*/
|
|
959
1055
|
this.selectedTileLength = 0;
|
|
960
|
-
this._selectedTileSet = new Set();
|
|
961
1056
|
|
|
962
1057
|
/**
|
|
963
1058
|
* Indicates whether or not the primitive is ready for use.
|
|
@@ -1096,6 +1191,7 @@ Object.defineProperties(GaussianSplatPrimitive.prototype, {
|
|
|
1096
1191
|
get: function () {
|
|
1097
1192
|
return (
|
|
1098
1193
|
!this._dirty &&
|
|
1194
|
+
!this._snapshotRebuildScheduler.isPending &&
|
|
1099
1195
|
(!defined(this._pendingSnapshot) ||
|
|
1100
1196
|
this._pendingSnapshot.state === SnapshotState.READY)
|
|
1101
1197
|
);
|
|
@@ -1197,14 +1293,15 @@ GaussianSplatPrimitive.prototype.isDestroyed = function () {
|
|
|
1197
1293
|
};
|
|
1198
1294
|
|
|
1199
1295
|
/**
|
|
1200
|
-
*
|
|
1201
|
-
*
|
|
1202
|
-
* It sets the dirty flag to true, indicating that the primitive needs to be rebuilt.
|
|
1296
|
+
* Marks the primitive dirty when a selected tile loads new content.
|
|
1297
|
+
* Loads outside the selected set do not affect the current snapshot.
|
|
1203
1298
|
* @param {Cesium3DTile} tile
|
|
1204
1299
|
* @private
|
|
1205
1300
|
*/
|
|
1206
1301
|
GaussianSplatPrimitive.prototype.onTileLoad = function (tile) {
|
|
1207
|
-
this.
|
|
1302
|
+
if (this._snapshotRebuildScheduler.hasSelectedTile(tile)) {
|
|
1303
|
+
this._dirty = true;
|
|
1304
|
+
}
|
|
1208
1305
|
};
|
|
1209
1306
|
|
|
1210
1307
|
/**
|
|
@@ -1711,43 +1808,32 @@ GaussianSplatPrimitive.prototype.update = function (frameState) {
|
|
|
1711
1808
|
return;
|
|
1712
1809
|
}
|
|
1713
1810
|
|
|
1811
|
+
const selectedTiles = tileset._selectedTiles;
|
|
1812
|
+
const hasSelectedTiles = selectedTiles.length !== 0;
|
|
1813
|
+
const statistics = tileset.statistics;
|
|
1814
|
+
const isBootstrap =
|
|
1815
|
+
!defined(this._snapshot) &&
|
|
1816
|
+
!defined(this._pendingSnapshot) &&
|
|
1817
|
+
!defined(this._drawCommand);
|
|
1818
|
+
const allowSnapshotRebuild = this._snapshotRebuildScheduler.update(
|
|
1819
|
+
getTimestamp(),
|
|
1820
|
+
{
|
|
1821
|
+
selectedTiles: selectedTiles,
|
|
1822
|
+
rebuildRequested: this._dirty,
|
|
1823
|
+
isBootstrap: isBootstrap,
|
|
1824
|
+
tilesLoaded: tileset.tilesLoaded,
|
|
1825
|
+
tilesInFlight:
|
|
1826
|
+
defined(statistics) &&
|
|
1827
|
+
(statistics.numberOfTilesProcessing > 0 ||
|
|
1828
|
+
statistics.numberOfPendingRequests > 0),
|
|
1829
|
+
hasCommittedSnapshot: defined(this._snapshot),
|
|
1830
|
+
},
|
|
1831
|
+
);
|
|
1832
|
+
|
|
1714
1833
|
if (this._sorterState === GaussianSplatSortingState.IDLE) {
|
|
1715
|
-
const selectedTilesChanged =
|
|
1716
|
-
tileset._selectedTiles.length !== 0 &&
|
|
1717
|
-
haveSelectedTilesChanged(this, tileset._selectedTiles);
|
|
1718
|
-
if (tileset._selectedTiles.length === 0) {
|
|
1719
|
-
this._selectedTilesStableFrames = 0;
|
|
1720
|
-
this._needsSnapshotRebuild = false;
|
|
1721
|
-
this._snapshotRebuildStallFrames = 0;
|
|
1722
|
-
} else if (selectedTilesChanged) {
|
|
1723
|
-
this._selectedTilesStableFrames = 0;
|
|
1724
|
-
} else {
|
|
1725
|
-
this._selectedTilesStableFrames++;
|
|
1726
|
-
}
|
|
1727
|
-
if (selectedTilesChanged || this._dirty) {
|
|
1728
|
-
this._needsSnapshotRebuild = true;
|
|
1729
|
-
}
|
|
1730
|
-
const isStable = this._selectedTilesStableFrames >= DEFAULT_STABLE_FRAMES;
|
|
1731
|
-
const isBootstrap =
|
|
1732
|
-
!defined(this._snapshot) &&
|
|
1733
|
-
!defined(this._pendingSnapshot) &&
|
|
1734
|
-
!defined(this._drawCommand);
|
|
1735
|
-
// This prevents an indefinite wait if selected tiles never settle completely.
|
|
1736
|
-
// In practice, this is the upper bound on "wait-for-stability" before forcing
|
|
1737
|
-
// a rebuild to avoid visible starvation.
|
|
1738
|
-
if (this._needsSnapshotRebuild && tileset._selectedTiles.length !== 0) {
|
|
1739
|
-
this._snapshotRebuildStallFrames++;
|
|
1740
|
-
} else {
|
|
1741
|
-
this._snapshotRebuildStallFrames = 0;
|
|
1742
|
-
}
|
|
1743
|
-
const allowRebuild =
|
|
1744
|
-
isStable ||
|
|
1745
|
-
isBootstrap ||
|
|
1746
|
-
this._snapshotRebuildStallFrames >= DEFAULT_MAX_SNAPSHOT_STALL_FRAMES;
|
|
1747
1834
|
const hasPendingWork =
|
|
1748
1835
|
this._dirty ||
|
|
1749
|
-
this.
|
|
1750
|
-
selectedTilesChanged ||
|
|
1836
|
+
this._snapshotRebuildScheduler.isPending ||
|
|
1751
1837
|
defined(this._pendingSnapshot) ||
|
|
1752
1838
|
defined(this._pendingSortPromise) ||
|
|
1753
1839
|
!defined(this._drawCommand);
|
|
@@ -1759,10 +1845,11 @@ GaussianSplatPrimitive.prototype.update = function (frameState) {
|
|
|
1759
1845
|
}
|
|
1760
1846
|
|
|
1761
1847
|
if (
|
|
1762
|
-
|
|
1763
|
-
this.
|
|
1764
|
-
|
|
1848
|
+
hasSelectedTiles &&
|
|
1849
|
+
this._snapshotRebuildScheduler.isPending &&
|
|
1850
|
+
allowSnapshotRebuild
|
|
1765
1851
|
) {
|
|
1852
|
+
this._snapshotRebuildScheduler.markRebuildStarted();
|
|
1766
1853
|
this._splatDataGeneration++;
|
|
1767
1854
|
this._activeSort = undefined;
|
|
1768
1855
|
this._sorterPromise = undefined;
|
|
@@ -1971,11 +2058,8 @@ GaussianSplatPrimitive.prototype.update = function (frameState) {
|
|
|
1971
2058
|
state: SnapshotState.BUILDING,
|
|
1972
2059
|
};
|
|
1973
2060
|
|
|
1974
|
-
this.selectedTileLength =
|
|
1975
|
-
this._selectedTileSet = new Set(tileset._selectedTiles);
|
|
2061
|
+
this.selectedTileLength = selectedTiles.length;
|
|
1976
2062
|
this._dirty = false;
|
|
1977
|
-
this._needsSnapshotRebuild = false;
|
|
1978
|
-
this._snapshotRebuildStallFrames = 0;
|
|
1979
2063
|
}
|
|
1980
2064
|
|
|
1981
2065
|
if (defined(this._pendingSnapshot)) {
|
|
@@ -2144,4 +2228,7 @@ GaussianSplatPrimitive.prototype.update = function (frameState) {
|
|
|
2144
2228
|
this._dirty = false;
|
|
2145
2229
|
};
|
|
2146
2230
|
|
|
2231
|
+
// For testing.
|
|
2232
|
+
GaussianSplatPrimitive._SnapshotRebuildScheduler = SnapshotRebuildScheduler;
|
|
2233
|
+
|
|
2147
2234
|
export default GaussianSplatPrimitive;
|
|
@@ -2,9 +2,11 @@ import Check from "../Core/Check.js";
|
|
|
2
2
|
import Frozen from "../Core/Frozen.js";
|
|
3
3
|
import defined from "../Core/defined.js";
|
|
4
4
|
import findMeshoptExtension from "./findMeshoptExtension.js";
|
|
5
|
-
import { MeshoptDecoder } from "meshoptimizer";
|
|
6
5
|
import ResourceLoader from "./ResourceLoader.js";
|
|
7
6
|
import ResourceLoaderState from "./ResourceLoaderState.js";
|
|
7
|
+
import TaskProcessor from "../Core/TaskProcessor.js";
|
|
8
|
+
|
|
9
|
+
const decodeMeshoptTaskProcessor = new TaskProcessor("decodeMeshopt");
|
|
8
10
|
|
|
9
11
|
/**
|
|
10
12
|
* Loads a glTF buffer view.
|
|
@@ -159,29 +161,39 @@ async function loadResources(loader) {
|
|
|
159
161
|
}
|
|
160
162
|
|
|
161
163
|
const bufferTypedArray = bufferLoader.typedArray;
|
|
162
|
-
|
|
164
|
+
let bufferViewTypedArray = new Uint8Array(
|
|
163
165
|
bufferTypedArray.buffer,
|
|
164
166
|
bufferTypedArray.byteOffset + loader._byteOffset,
|
|
165
167
|
loader._byteLength,
|
|
166
168
|
);
|
|
167
169
|
|
|
170
|
+
if (loader._hasMeshopt) {
|
|
171
|
+
// The buffer can be shared with other cached resources. Copy the encoded
|
|
172
|
+
// range before transferring it to the worker so the cache stays intact.
|
|
173
|
+
bufferViewTypedArray = new Uint8Array(bufferViewTypedArray);
|
|
174
|
+
}
|
|
175
|
+
|
|
168
176
|
// Unload the buffer
|
|
169
177
|
loader.unload();
|
|
170
178
|
|
|
171
179
|
loader._typedArray = bufferViewTypedArray;
|
|
172
180
|
if (loader._hasMeshopt) {
|
|
173
|
-
const
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
loader.
|
|
182
|
-
loader._meshoptFilter,
|
|
181
|
+
const result = await decodeMeshoptTaskProcessor.scheduleTask(
|
|
182
|
+
{
|
|
183
|
+
source: loader._typedArray,
|
|
184
|
+
count: loader._meshoptCount,
|
|
185
|
+
byteStride: loader._meshoptByteStride,
|
|
186
|
+
mode: loader._meshoptMode,
|
|
187
|
+
filter: loader._meshoptFilter,
|
|
188
|
+
},
|
|
189
|
+
[loader._typedArray.buffer],
|
|
183
190
|
);
|
|
184
|
-
|
|
191
|
+
|
|
192
|
+
if (loader.isDestroyed()) {
|
|
193
|
+
return;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
loader._typedArray = new Uint8Array(result);
|
|
185
197
|
}
|
|
186
198
|
|
|
187
199
|
loader._state = ResourceLoaderState.READY;
|
|
@@ -4,7 +4,7 @@ import defined from "../Core/defined.js";
|
|
|
4
4
|
import RuntimeError from "../Core/RuntimeError.js";
|
|
5
5
|
import ResourceLoader from "./ResourceLoader.js";
|
|
6
6
|
import ResourceLoaderState from "./ResourceLoaderState.js";
|
|
7
|
-
import
|
|
7
|
+
import SpzDecoder from "./SpzDecoder.js";
|
|
8
8
|
|
|
9
9
|
// Cumulative number of SH coefficient floats per splat per channel for each
|
|
10
10
|
// degree. Degree 0 has no extra SH data (base color is stored separately in
|
|
@@ -234,9 +234,10 @@ class GltfSpzLoader extends ResourceLoader {
|
|
|
234
234
|
}
|
|
235
235
|
}
|
|
236
236
|
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
237
|
+
// Buffer views can be shared by cached resources. Transfer a private copy
|
|
238
|
+
// so decoding does not detach the cached source.
|
|
239
|
+
const spzData = new Uint8Array(this._bufferViewTypedArray);
|
|
240
|
+
const decodePromise = SpzDecoder.decode(spzData);
|
|
240
241
|
|
|
241
242
|
if (!defined(decodePromise)) {
|
|
242
243
|
return false;
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import defined from "../Core/defined.js";
|
|
2
|
+
import DeveloperError from "../Core/DeveloperError.js";
|
|
3
|
+
import getAbsoluteUri from "../Core/getAbsoluteUri.js";
|
|
4
|
+
import TaskProcessor from "../Core/TaskProcessor.js";
|
|
5
|
+
|
|
6
|
+
const defaultWorkerModuleId = "decodeSpz";
|
|
7
|
+
|
|
8
|
+
function getDecoderTaskProcessor() {
|
|
9
|
+
let taskProcessor = SpzDecoder._decoderTaskProcessor;
|
|
10
|
+
if (!defined(taskProcessor)) {
|
|
11
|
+
const workerModuleUrl = SpzDecoder._workerModuleUrl;
|
|
12
|
+
const workerPath = defined(workerModuleUrl)
|
|
13
|
+
? getAbsoluteUri(workerModuleUrl)
|
|
14
|
+
: defaultWorkerModuleId;
|
|
15
|
+
taskProcessor = new TaskProcessor(workerPath);
|
|
16
|
+
SpzDecoder._decoderTaskProcessor = taskProcessor;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
return taskProcessor;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Configures the Web Worker module used to decode SPZ-compressed Gaussian
|
|
24
|
+
* splats.
|
|
25
|
+
*
|
|
26
|
+
* @alias SpzDecoder
|
|
27
|
+
* @namespace
|
|
28
|
+
*
|
|
29
|
+
* @experimental This feature is not final and is subject to change without
|
|
30
|
+
* Cesium's standard deprecation policy.
|
|
31
|
+
*/
|
|
32
|
+
function SpzDecoder() {}
|
|
33
|
+
|
|
34
|
+
Object.defineProperties(SpzDecoder, {
|
|
35
|
+
/**
|
|
36
|
+
* The URL of the ECMAScript Web Worker module that decodes SPZ data. Set
|
|
37
|
+
* this before the first SPZ decode to use a decoder other than Cesium's
|
|
38
|
+
* bundled <code>Workers/decodeSpz.js</code> worker. Relative URLs are
|
|
39
|
+
* resolved relative to the document URL.
|
|
40
|
+
*
|
|
41
|
+
* To apply a separate Content Security Policy to the decoder, serve the
|
|
42
|
+
* module as a separate, same-origin resource. Cross-origin URLs use a
|
|
43
|
+
* <code>blob:</code> worker fallback, which inherits the document's policy.
|
|
44
|
+
*
|
|
45
|
+
* The module must use {@link createTaskProcessorWorker}, receive an object
|
|
46
|
+
* with a <code>spzData</code> {@link Uint8Array}, and return the gcloud
|
|
47
|
+
* object produced by <code>@spz-loader/core</code>. It must transfer the
|
|
48
|
+
* buffers for its typed-array attributes.
|
|
49
|
+
*
|
|
50
|
+
* @memberof SpzDecoder
|
|
51
|
+
* @type {string|undefined}
|
|
52
|
+
* @default undefined
|
|
53
|
+
* @experimental This feature is not final and is subject to change without
|
|
54
|
+
* Cesium's standard deprecation policy.
|
|
55
|
+
*/
|
|
56
|
+
workerModuleUrl: {
|
|
57
|
+
get: function () {
|
|
58
|
+
return SpzDecoder._workerModuleUrl;
|
|
59
|
+
},
|
|
60
|
+
set: function (value) {
|
|
61
|
+
if (defined(SpzDecoder._decoderTaskProcessor)) {
|
|
62
|
+
throw new DeveloperError(
|
|
63
|
+
"SpzDecoder.workerModuleUrl must be configured before the first SPZ decode.",
|
|
64
|
+
);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
if (defined(value) && (typeof value !== "string" || value.length === 0)) {
|
|
68
|
+
throw new DeveloperError(
|
|
69
|
+
"SpzDecoder.workerModuleUrl must be a non-empty string or undefined.",
|
|
70
|
+
);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
SpzDecoder._workerModuleUrl = value;
|
|
74
|
+
},
|
|
75
|
+
},
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Decodes SPZ data in the configured Web Worker.
|
|
80
|
+
*
|
|
81
|
+
* @param {Uint8Array} spzData The compressed SPZ data. Its backing buffer is
|
|
82
|
+
* transferred to the worker.
|
|
83
|
+
* @returns {Promise<object>|undefined} A promise that resolves to the gcloud
|
|
84
|
+
* decode result, or undefined when the worker is busy.
|
|
85
|
+
* @private
|
|
86
|
+
*/
|
|
87
|
+
SpzDecoder.decode = function (spzData) {
|
|
88
|
+
return getDecoderTaskProcessor().scheduleTask({ spzData: spzData }, [
|
|
89
|
+
spzData.buffer,
|
|
90
|
+
]);
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
SpzDecoder._decoderTaskProcessor = undefined;
|
|
94
|
+
SpzDecoder._workerModuleUrl = undefined;
|
|
95
|
+
|
|
96
|
+
// Exposed for testing purposes.
|
|
97
|
+
SpzDecoder._resetForTesting = function () {
|
|
98
|
+
const taskProcessor = SpzDecoder._decoderTaskProcessor;
|
|
99
|
+
if (defined(taskProcessor) && !taskProcessor.isDestroyed()) {
|
|
100
|
+
taskProcessor.destroy();
|
|
101
|
+
}
|
|
102
|
+
SpzDecoder._decoderTaskProcessor = undefined;
|
|
103
|
+
SpzDecoder._workerModuleUrl = undefined;
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
export default SpzDecoder;
|