bruce-cesium 7.7.3 → 7.7.5
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/dist/bruce-cesium.es5.js +542 -94
- package/dist/bruce-cesium.es5.js.map +1 -1
- package/dist/bruce-cesium.umd.js +540 -92
- package/dist/bruce-cesium.umd.js.map +1 -1
- package/dist/lib/bruce-cesium.js +1 -1
- package/dist/lib/rendering/entity-render-engine-model3d.js +168 -71
- package/dist/lib/rendering/entity-render-engine-model3d.js.map +1 -1
- package/dist/lib/rendering/xgrids-render-engine.js +370 -19
- package/dist/lib/rendering/xgrids-render-engine.js.map +1 -1
- package/dist/types/bruce-cesium.d.ts +1 -1
- package/dist/types/rendering/xgrids-render-engine.d.ts +24 -0
- package/package.json +2 -2
package/dist/bruce-cesium.umd.js
CHANGED
|
@@ -28110,10 +28110,13 @@
|
|
|
28110
28110
|
})(exports.DataSourceStaticKmlManager || (exports.DataSourceStaticKmlManager = {}));
|
|
28111
28111
|
|
|
28112
28112
|
(function (XGridsRenderEngine) {
|
|
28113
|
+
/*
|
|
28114
|
+
* Loads a scan with optional SDK tuning and per-viewer budget control.
|
|
28115
|
+
*/
|
|
28113
28116
|
function Render(params) {
|
|
28114
|
-
var _a, _b, _c;
|
|
28117
|
+
var _a, _b, _c, _d;
|
|
28115
28118
|
const { api, viewer, tileset } = params;
|
|
28116
|
-
if (
|
|
28119
|
+
if (typeof LCCRender === "undefined" || typeof (LCCRender === null || LCCRender === void 0 ? void 0 : LCCRender.load) !== "function") {
|
|
28117
28120
|
console.warn("[XGridsRenderEngine] Render() LCCRender library not available.");
|
|
28118
28121
|
return null;
|
|
28119
28122
|
}
|
|
@@ -28156,6 +28159,46 @@
|
|
|
28156
28159
|
if (loadUrl.indexOf("?") !== -1) {
|
|
28157
28160
|
loadUrl = loadUrl.split("?")[0];
|
|
28158
28161
|
}
|
|
28162
|
+
let maxSplats = 6000000;
|
|
28163
|
+
/*
|
|
28164
|
+
* Configures optional LOD capabilities once metadata or initial geometry is ready.
|
|
28165
|
+
*/
|
|
28166
|
+
const configure = (object, ready) => {
|
|
28167
|
+
var _a, _b, _c;
|
|
28168
|
+
if (!object || object["_nextspaceLodRemoved"] || object["_nextspaceLodConfigured"] || ((_a = viewer.isDestroyed) === null || _a === void 0 ? void 0 : _a.call(viewer))) {
|
|
28169
|
+
return;
|
|
28170
|
+
}
|
|
28171
|
+
try {
|
|
28172
|
+
if (typeof object.setMaxSplats !== "function") {
|
|
28173
|
+
return;
|
|
28174
|
+
}
|
|
28175
|
+
const lods = typeof object.getLodInfos === "function" ? object.getLodInfos() : undefined;
|
|
28176
|
+
const adaptive = (LCCRender.nextspaceAdaptiveLod === 1 &&
|
|
28177
|
+
typeof object.setNextspaceMetadataCallback === "function" &&
|
|
28178
|
+
Array.isArray(lods) &&
|
|
28179
|
+
typeof object.setVisible === "function" &&
|
|
28180
|
+
typeof object.setLodAutoLevelUp === "function");
|
|
28181
|
+
// Unpatched SDKs still need the legacy clamp to avoid their fixed LOD shortcut.
|
|
28182
|
+
const budget = !adaptive && (lods === null || lods === void 0 ? void 0 : lods[0]) > maxSplats && (lods === null || lods === void 0 ? void 0 : lods[1]) > 0
|
|
28183
|
+
? Math.min(maxSplats, lods[1]) : maxSplats;
|
|
28184
|
+
object.setMaxSplats(budget);
|
|
28185
|
+
// A requested fly-to needs its initial data before off-screen culling can take over.
|
|
28186
|
+
if (adaptive &&
|
|
28187
|
+
(!params.flyTo || ready) &&
|
|
28188
|
+
((_b = viewer.scene.preUpdate) === null || _b === void 0 ? void 0 : _b.addEventListener) &&
|
|
28189
|
+
((_c = viewer.scene.postRender) === null || _c === void 0 ? void 0 : _c.addEventListener)) {
|
|
28190
|
+
const controller = viewer["_nextspaceXGridsLod"] ||
|
|
28191
|
+
(viewer["_nextspaceXGridsLod"] = new AdaptiveLod(viewer));
|
|
28192
|
+
controller.Add(object, maxSplats);
|
|
28193
|
+
controller.Update();
|
|
28194
|
+
}
|
|
28195
|
+
object["_nextspaceLodConfigured"] = !params.flyTo || ready;
|
|
28196
|
+
}
|
|
28197
|
+
catch (error) {
|
|
28198
|
+
// Optional SDK tuning must not abort its metadata parsing or the Cesium render loop.
|
|
28199
|
+
console.warn("[XGridsRenderEngine] Optional LOD setup unavailable.", error);
|
|
28200
|
+
}
|
|
28201
|
+
};
|
|
28159
28202
|
const obj = LCCRender.load({
|
|
28160
28203
|
camera: viewer.camera,
|
|
28161
28204
|
scene: viewer.scene,
|
|
@@ -28169,24 +28212,19 @@
|
|
|
28169
28212
|
// When true it makes the new pieces fade-in.
|
|
28170
28213
|
// The look is similar to sectioning in cesium. Might be a nice setting.
|
|
28171
28214
|
useLoadingEffect: false
|
|
28172
|
-
}, async () => {
|
|
28173
|
-
var _a, _b;
|
|
28174
|
-
|
|
28175
|
-
|
|
28176
|
-
|
|
28177
|
-
const HARD_MIN = 1000000;
|
|
28178
|
-
const HARD_MAX = 20000000;
|
|
28179
|
-
const maxSplats = Math.max(lods ? lods[0] || 0 : 0, HARD_MIN);
|
|
28180
|
-
obj.setMaxSplats(Math.min(HARD_MAX, maxSplats));
|
|
28181
|
-
if (maxSplats >= HARD_MAX) {
|
|
28182
|
-
console.warn("Reduced splat quality due to the number of splats being too large. Was: \"" + maxSplats + "\", now is: \"" + HARD_MAX + "\".");
|
|
28215
|
+
}, async (loaded) => {
|
|
28216
|
+
var _a, _b, _c;
|
|
28217
|
+
const object = loaded || obj;
|
|
28218
|
+
if (!object || object["_nextspaceLodRemoved"] || ((_a = viewer.isDestroyed) === null || _a === void 0 ? void 0 : _a.call(viewer))) {
|
|
28219
|
+
return;
|
|
28183
28220
|
}
|
|
28221
|
+
configure(object, true);
|
|
28184
28222
|
// Auto fly to.
|
|
28185
28223
|
if (params.flyTo) {
|
|
28186
|
-
const pos3d =
|
|
28224
|
+
const pos3d = typeof object.getBounds === "function" ? (_b = object.getBounds()) === null || _b === void 0 ? void 0 : _b.origin : undefined;
|
|
28187
28225
|
if (pos3d && BModels.Cartes.ValidateCartes3(pos3d)) {
|
|
28188
28226
|
const altered = await exports.DrawingUtils.RaisePos3d(viewer, pos3d, 300);
|
|
28189
|
-
if (altered && BModels.Cartes.ValidateCartes3(altered)) {
|
|
28227
|
+
if (!object["_nextspaceLodRemoved"] && !((_c = viewer.isDestroyed) === null || _c === void 0 ? void 0 : _c.call(viewer)) && altered && BModels.Cartes.ValidateCartes3(altered)) {
|
|
28190
28228
|
viewer.scene.camera.flyTo({
|
|
28191
28229
|
destination: altered,
|
|
28192
28230
|
orientation: {
|
|
@@ -28201,14 +28239,46 @@
|
|
|
28201
28239
|
}
|
|
28202
28240
|
}
|
|
28203
28241
|
});
|
|
28242
|
+
if (!obj) {
|
|
28243
|
+
return null;
|
|
28244
|
+
}
|
|
28245
|
+
try {
|
|
28246
|
+
const sdkBudget = typeof obj.getCurrentConfig === "function" ? (_d = obj.getCurrentConfig()) === null || _d === void 0 ? void 0 : _d.maxLoadSplatCount : undefined;
|
|
28247
|
+
// Preserve the SDK's mobile and weak-GPU limits before applying any temporary startup cap.
|
|
28248
|
+
maxSplats = Number.isFinite(sdkBudget) && sdkBudget > 0 && sdkBudget <= 2000000 ? sdkBudget : 6000000;
|
|
28249
|
+
if (LCCRender.nextspaceMetadataReady === 1 &&
|
|
28250
|
+
typeof obj.setNextspaceMetadataCallback === "function" &&
|
|
28251
|
+
typeof obj.setMaxSplats === "function") {
|
|
28252
|
+
obj.setNextspaceMetadataCallback((object) => configure(object, false));
|
|
28253
|
+
obj.setMaxSplats(Math.min(maxSplats, 1000000));
|
|
28254
|
+
}
|
|
28255
|
+
}
|
|
28256
|
+
catch (error) {
|
|
28257
|
+
console.warn("[XGridsRenderEngine] Optional startup LOD setup unavailable.", error);
|
|
28258
|
+
}
|
|
28259
|
+
if (typeof (obj === null || obj === void 0 ? void 0 : obj.setRenderState) === "function") {
|
|
28260
|
+
// Splats must respect nearer meshes already drawn in the same Cesium pass.
|
|
28261
|
+
obj.setRenderState({
|
|
28262
|
+
depthTest: {
|
|
28263
|
+
enabled: true,
|
|
28264
|
+
func: Cesium.WebGLConstants.LEQUAL
|
|
28265
|
+
},
|
|
28266
|
+
// Transparent Gaussian edges must not occlude the splats blended behind them.
|
|
28267
|
+
depthMask: false
|
|
28268
|
+
});
|
|
28269
|
+
}
|
|
28204
28270
|
if (typeof (obj === null || obj === void 0 ? void 0 : obj.setVisible) === "function") {
|
|
28205
28271
|
obj.setVisible(true);
|
|
28206
28272
|
}
|
|
28207
28273
|
exports.TilesetRenderEngine.WatchDateRange(viewer, obj, tileset);
|
|
28208
28274
|
// Highest LOD.
|
|
28209
|
-
obj.setStartLod
|
|
28275
|
+
if (typeof obj.setStartLod === "function") {
|
|
28276
|
+
obj.setStartLod(0);
|
|
28277
|
+
}
|
|
28210
28278
|
// Max distance for rendering.
|
|
28211
|
-
obj.setMaxDistance
|
|
28279
|
+
if (typeof obj.setMaxDistance === "function") {
|
|
28280
|
+
obj.setMaxDistance(800);
|
|
28281
|
+
}
|
|
28212
28282
|
// Adjust LODs based on camera distance.
|
|
28213
28283
|
if (typeof obj.setLodAutoLevelUp === "function") {
|
|
28214
28284
|
obj.setLodAutoLevelUp(true);
|
|
@@ -28216,18 +28286,299 @@
|
|
|
28216
28286
|
return obj;
|
|
28217
28287
|
}
|
|
28218
28288
|
XGridsRenderEngine.Render = Render;
|
|
28289
|
+
/*
|
|
28290
|
+
* Detaches optional tuning before unloading the scan.
|
|
28291
|
+
*/
|
|
28219
28292
|
function Remove(viewer, renderObject) {
|
|
28293
|
+
var _a;
|
|
28220
28294
|
if (!renderObject) {
|
|
28221
28295
|
return;
|
|
28222
28296
|
}
|
|
28223
|
-
|
|
28297
|
+
renderObject["_nextspaceLodRemoved"] = true;
|
|
28298
|
+
delete renderObject.nextspaceOnMetadata;
|
|
28299
|
+
(_a = viewer === null || viewer === void 0 ? void 0 : viewer["_nextspaceXGridsLod"]) === null || _a === void 0 ? void 0 : _a.Remove(renderObject);
|
|
28300
|
+
exports.TilesetRenderEngine.UnwatchDateRange(viewer, renderObject);
|
|
28301
|
+
if (typeof LCCRender === "undefined" || typeof (LCCRender === null || LCCRender === void 0 ? void 0 : LCCRender.unload) !== "function") {
|
|
28224
28302
|
console.warn("[XGridsRenderEngine] Remove() LCCRender library not available.");
|
|
28225
28303
|
return;
|
|
28226
28304
|
}
|
|
28227
|
-
exports.TilesetRenderEngine.UnwatchDateRange(viewer, renderObject);
|
|
28228
28305
|
LCCRender.unload(renderObject);
|
|
28229
28306
|
}
|
|
28230
28307
|
XGridsRenderEngine.Remove = Remove;
|
|
28308
|
+
/*
|
|
28309
|
+
* Shares a bounded splat budget across visible scans without overriding layer or timeline visibility.
|
|
28310
|
+
*/
|
|
28311
|
+
class AdaptiveLod {
|
|
28312
|
+
/*
|
|
28313
|
+
* Observes scene updates and rendered frames for this viewer only.
|
|
28314
|
+
*/
|
|
28315
|
+
constructor(viewer) {
|
|
28316
|
+
this.viewer = viewer;
|
|
28317
|
+
this.entries = [];
|
|
28318
|
+
this.removals = [];
|
|
28319
|
+
this.lastUpdate = -Infinity;
|
|
28320
|
+
this.lastAllocation = -Infinity;
|
|
28321
|
+
this.lastFrame = 0;
|
|
28322
|
+
this.lastMove = 0;
|
|
28323
|
+
this.slowSince = 0;
|
|
28324
|
+
this.fastSince = 0;
|
|
28325
|
+
this.lastChange = -Infinity;
|
|
28326
|
+
this.scale = 1;
|
|
28327
|
+
this.position = new Cesium.Cartesian3();
|
|
28328
|
+
this.direction = new Cesium.Cartesian3();
|
|
28329
|
+
this.havePose = false;
|
|
28330
|
+
this.removals.push(viewer.scene.preUpdate.addEventListener(() => {
|
|
28331
|
+
try {
|
|
28332
|
+
this.Update();
|
|
28333
|
+
}
|
|
28334
|
+
catch (error) {
|
|
28335
|
+
console.warn("[XGridsRenderEngine] Optional LOD controller disabled.", error);
|
|
28336
|
+
this.Dispose();
|
|
28337
|
+
}
|
|
28338
|
+
}));
|
|
28339
|
+
this.removals.push(viewer.scene.postRender.addEventListener(() => {
|
|
28340
|
+
const camera = viewer.scene.camera;
|
|
28341
|
+
const moving = this.havePose && (Cesium.Cartesian3.distanceSquared(camera.positionWC, this.position) > 0.000001 ||
|
|
28342
|
+
Cesium.Cartesian3.distanceSquared(camera.directionWC, this.direction) > 0.00000001);
|
|
28343
|
+
Cesium.Cartesian3.clone(camera.positionWC, this.position);
|
|
28344
|
+
Cesium.Cartesian3.clone(camera.directionWC, this.direction);
|
|
28345
|
+
this.havePose = true;
|
|
28346
|
+
this.ObserveFrame(performance.now(), moving);
|
|
28347
|
+
}));
|
|
28348
|
+
}
|
|
28349
|
+
/*
|
|
28350
|
+
* Registers a scan while preserving the caller's visibility intent.
|
|
28351
|
+
*/
|
|
28352
|
+
Add(object, maxBudget) {
|
|
28353
|
+
var _a, _b, _c, _d;
|
|
28354
|
+
if (this.entries.some(entry => entry.object === object)) {
|
|
28355
|
+
return;
|
|
28356
|
+
}
|
|
28357
|
+
if (typeof object.setMaxSplats !== "function") {
|
|
28358
|
+
return;
|
|
28359
|
+
}
|
|
28360
|
+
const lods = typeof object.getLodInfos === "function" ? object.getLodInfos() : undefined;
|
|
28361
|
+
const finest = lods === null || lods === void 0 ? void 0 : lods[0];
|
|
28362
|
+
const coarsest = (lods === null || lods === void 0 ? void 0 : lods.length) > 1 ? lods[lods.length - 1] : 0;
|
|
28363
|
+
const entry = {
|
|
28364
|
+
object, maxBudget,
|
|
28365
|
+
capacity: Number.isFinite(finest) && finest > 0 ? Math.min(maxBudget, finest) : maxBudget,
|
|
28366
|
+
minimum: Number.isFinite(coarsest) && coarsest > 0 ? Math.min(maxBudget, coarsest) : 0,
|
|
28367
|
+
wantedVisible: ((_b = (_a = object.getCurrentConfig) === null || _a === void 0 ? void 0 : _a.call(object)) === null || _b === void 0 ? void 0 : _b.visible) !== false,
|
|
28368
|
+
visible: ((_d = (_c = object.getCurrentConfig) === null || _c === void 0 ? void 0 : _c.call(object)) === null || _d === void 0 ? void 0 : _d.visible) !== false,
|
|
28369
|
+
culled: false, setVisible: object.setVisible, budget: -1, nodeBudget: -1,
|
|
28370
|
+
radiusPixels: Infinity, surfaceDistance: Infinity, weight: 1, near: false
|
|
28371
|
+
};
|
|
28372
|
+
if (typeof entry.setVisible === "function") {
|
|
28373
|
+
object.setVisible = (visible) => {
|
|
28374
|
+
entry.wantedVisible = !!visible;
|
|
28375
|
+
this.applyVisibility(entry);
|
|
28376
|
+
this.lastUpdate = -Infinity;
|
|
28377
|
+
this.lastAllocation = -Infinity;
|
|
28378
|
+
};
|
|
28379
|
+
}
|
|
28380
|
+
this.entries.push(entry);
|
|
28381
|
+
this.lastMove = performance.now();
|
|
28382
|
+
this.lastUpdate = -Infinity;
|
|
28383
|
+
this.lastAllocation = -Infinity;
|
|
28384
|
+
}
|
|
28385
|
+
/*
|
|
28386
|
+
* Combines explicit visibility with temporary camera culling.
|
|
28387
|
+
*/
|
|
28388
|
+
applyVisibility(entry) {
|
|
28389
|
+
const visible = entry.wantedVisible && !entry.culled;
|
|
28390
|
+
if (entry.visible !== visible && typeof entry.setVisible === "function") {
|
|
28391
|
+
entry.visible = visible;
|
|
28392
|
+
entry.setVisible.call(entry.object, visible);
|
|
28393
|
+
this.viewer.scene.requestRender();
|
|
28394
|
+
}
|
|
28395
|
+
}
|
|
28396
|
+
/*
|
|
28397
|
+
* Render pressure uses elapsed wall time because a paused timeline must still adapt.
|
|
28398
|
+
*/
|
|
28399
|
+
ObserveFrame(now, moving) {
|
|
28400
|
+
const gap = now - this.lastFrame;
|
|
28401
|
+
this.lastFrame = now;
|
|
28402
|
+
if (moving) {
|
|
28403
|
+
this.lastMove = now;
|
|
28404
|
+
}
|
|
28405
|
+
if (!moving || gap <= 0 || gap > 1000) {
|
|
28406
|
+
this.slowSince = this.fastSince = 0;
|
|
28407
|
+
return;
|
|
28408
|
+
}
|
|
28409
|
+
this.slowSince = gap > 40 ? this.slowSince || now : 0;
|
|
28410
|
+
this.fastSince = gap < 22 ? this.fastSince || now : 0;
|
|
28411
|
+
if (now - this.lastChange < 4000) {
|
|
28412
|
+
return;
|
|
28413
|
+
}
|
|
28414
|
+
if (this.slowSince && now - this.slowSince >= 1500 && this.scale > 0.25) {
|
|
28415
|
+
this.scale = Math.max(0.25, this.scale * 0.75);
|
|
28416
|
+
this.lastChange = now;
|
|
28417
|
+
this.slowSince = this.fastSince = 0;
|
|
28418
|
+
this.lastUpdate = -Infinity;
|
|
28419
|
+
}
|
|
28420
|
+
else if (this.fastSince && now - this.fastSince >= 6000 && this.scale < 1) {
|
|
28421
|
+
this.scale = Math.min(1, this.scale + 0.125);
|
|
28422
|
+
this.lastChange = now;
|
|
28423
|
+
this.slowSince = this.fastSince = 0;
|
|
28424
|
+
this.lastUpdate = -Infinity;
|
|
28425
|
+
}
|
|
28426
|
+
}
|
|
28427
|
+
/*
|
|
28428
|
+
* Estimates visible screen coverage and distance, failing open for unknown bounds.
|
|
28429
|
+
*/
|
|
28430
|
+
measure(entry) {
|
|
28431
|
+
var _a;
|
|
28432
|
+
entry.weight = 1;
|
|
28433
|
+
entry.radiusPixels = entry.surfaceDistance = Infinity;
|
|
28434
|
+
try {
|
|
28435
|
+
const object = entry.object;
|
|
28436
|
+
const bounds = (_a = object.getBounds) === null || _a === void 0 ? void 0 : _a.call(object);
|
|
28437
|
+
const matrix = object.modelMatrix;
|
|
28438
|
+
const camera = this.viewer.scene.camera;
|
|
28439
|
+
const width = this.viewer.scene.drawingBufferWidth;
|
|
28440
|
+
const height = this.viewer.scene.drawingBufferHeight;
|
|
28441
|
+
if (!(bounds === null || bounds === void 0 ? void 0 : bounds.min) || !(bounds === null || bounds === void 0 ? void 0 : bounds.max) || !matrix || !(width > 0 && height > 0)) {
|
|
28442
|
+
entry.culled = false;
|
|
28443
|
+
return;
|
|
28444
|
+
}
|
|
28445
|
+
const center = Cesium.Cartesian3.midpoint(bounds.min, bounds.max, new Cesium.Cartesian3());
|
|
28446
|
+
Cesium.Matrix4.multiplyByPoint(matrix, center, center);
|
|
28447
|
+
const scale = Cesium.Matrix4.getMaximumScale(matrix);
|
|
28448
|
+
const radius = Cesium.Cartesian3.distance(bounds.min, bounds.max) * scale * 0.55 + 1;
|
|
28449
|
+
const distance = Cesium.Cartesian3.distance(camera.positionWC, center);
|
|
28450
|
+
const pixel = camera.frustum.getPixelDimensions(width, height, Math.max(1, distance), 1, new Cesium.Cartesian2());
|
|
28451
|
+
const pixels = radius / Math.max(pixel.x, pixel.y);
|
|
28452
|
+
if (!Number.isFinite(pixels) || !(radius > 0)) {
|
|
28453
|
+
entry.culled = false;
|
|
28454
|
+
return;
|
|
28455
|
+
}
|
|
28456
|
+
const sphere = new Cesium.BoundingSphere(center, radius);
|
|
28457
|
+
const frustum = camera.frustum.computeCullingVolume(camera.positionWC, camera.directionWC, camera.upWC);
|
|
28458
|
+
const outside = frustum.computeVisibility(sphere) === Cesium.Intersect.OUTSIDE;
|
|
28459
|
+
entry.culled = outside || pixels < (entry.culled ? 1.5 : 0.75);
|
|
28460
|
+
entry.radiusPixels = pixels;
|
|
28461
|
+
entry.weight = Math.pow(Math.min(1, Math.max(0.05, pixels / height)), 2);
|
|
28462
|
+
const local = Cesium.Matrix4.multiplyByPoint(Cesium.Matrix4.inverse(matrix, new Cesium.Matrix4()), camera.positionWC, new Cesium.Cartesian3());
|
|
28463
|
+
const nearest = new Cesium.Cartesian3(Cesium.Math.clamp(local.x, bounds.min.x, bounds.max.x), Cesium.Math.clamp(local.y, bounds.min.y, bounds.max.y), Cesium.Math.clamp(local.z, bounds.min.z, bounds.max.z));
|
|
28464
|
+
entry.surfaceDistance = Cesium.Cartesian3.distance(local, nearest) * scale;
|
|
28465
|
+
}
|
|
28466
|
+
catch {
|
|
28467
|
+
// Unknown bounds or a changed optional SDK must fail open instead of hiding the scan.
|
|
28468
|
+
entry.culled = false;
|
|
28469
|
+
}
|
|
28470
|
+
}
|
|
28471
|
+
/*
|
|
28472
|
+
* Allocates the shared hardware budget across visible scans with hysteresis.
|
|
28473
|
+
*/
|
|
28474
|
+
Update(now = performance.now()) {
|
|
28475
|
+
var _a, _b;
|
|
28476
|
+
if ((_b = (_a = this.viewer).isDestroyed) === null || _b === void 0 ? void 0 : _b.call(_a)) {
|
|
28477
|
+
this.Dispose();
|
|
28478
|
+
return;
|
|
28479
|
+
}
|
|
28480
|
+
if (now - this.lastUpdate < 250) {
|
|
28481
|
+
return;
|
|
28482
|
+
}
|
|
28483
|
+
this.lastUpdate = now;
|
|
28484
|
+
// A still view can recover detail gradually without treating missing frames as a slow GPU.
|
|
28485
|
+
if (now - this.lastMove > 3000 && now - this.lastChange > 6000 && this.scale < 1) {
|
|
28486
|
+
this.scale = Math.min(1, this.scale + 0.125);
|
|
28487
|
+
this.lastChange = now;
|
|
28488
|
+
}
|
|
28489
|
+
for (const entry of this.entries) {
|
|
28490
|
+
this.measure(entry);
|
|
28491
|
+
this.applyVisibility(entry);
|
|
28492
|
+
}
|
|
28493
|
+
const visible = this.entries.filter(entry => entry.wantedVisible && !entry.culled);
|
|
28494
|
+
if (!visible.length || now - this.lastAllocation < 2000) {
|
|
28495
|
+
return;
|
|
28496
|
+
}
|
|
28497
|
+
this.lastAllocation = now;
|
|
28498
|
+
const maximum = Math.max(...visible.map(entry => entry.maxBudget));
|
|
28499
|
+
const minimum = visible.reduce((sum, entry) => sum + Math.min(entry.capacity, entry.minimum), 0);
|
|
28500
|
+
// Preserve authored coarse coverage when it fits; dropping below a whole tile can erase a scan.
|
|
28501
|
+
const reserve = minimum <= maximum;
|
|
28502
|
+
let remaining = Math.max(maximum * this.scale, reserve ? minimum : 0);
|
|
28503
|
+
const allocations = new Map();
|
|
28504
|
+
visible.forEach(entry => {
|
|
28505
|
+
const floor = reserve ? Math.min(entry.capacity, entry.minimum) : 0;
|
|
28506
|
+
allocations.set(entry, floor);
|
|
28507
|
+
remaining -= floor;
|
|
28508
|
+
});
|
|
28509
|
+
let pending = visible.filter(entry => allocations.get(entry) < entry.capacity);
|
|
28510
|
+
while (pending.length) {
|
|
28511
|
+
const totalWeight = pending.reduce((sum, entry) => sum + entry.weight, 0);
|
|
28512
|
+
const capped = pending.filter(entry => remaining * entry.weight / totalWeight >= entry.capacity - allocations.get(entry));
|
|
28513
|
+
if (!capped.length) {
|
|
28514
|
+
pending.forEach(entry => allocations.set(entry, allocations.get(entry) + remaining * entry.weight / totalWeight));
|
|
28515
|
+
break;
|
|
28516
|
+
}
|
|
28517
|
+
capped.forEach(entry => {
|
|
28518
|
+
remaining -= entry.capacity - allocations.get(entry);
|
|
28519
|
+
allocations.set(entry, entry.capacity);
|
|
28520
|
+
});
|
|
28521
|
+
pending = pending.filter(entry => allocations.get(entry) < entry.capacity);
|
|
28522
|
+
}
|
|
28523
|
+
for (const entry of visible) {
|
|
28524
|
+
const allocation = allocations.get(entry);
|
|
28525
|
+
const step = allocation < 250000 ? 10000 : 250000;
|
|
28526
|
+
const budget = allocation >= entry.capacity ? entry.capacity : Math.max(1, reserve ? entry.minimum : 0, Math.floor(allocation / step) * step);
|
|
28527
|
+
const near = entry.surfaceDistance < (entry.near ? 20 : 12) && entry.radiusPixels > (entry.near ? 80 : 120);
|
|
28528
|
+
entry.near = near;
|
|
28529
|
+
const ceiling = entry.maxBudget <= 2000000 ? entry.maxBudget / 2 : near ? 4000000 : 2000000;
|
|
28530
|
+
const nodeBudget = Math.max(1, Math.min(ceiling, entry.capacity <= ceiling ? budget : budget * (near ? 2 / 3 : 1 / 3)));
|
|
28531
|
+
if (entry.budget !== budget) {
|
|
28532
|
+
entry.object.setMaxSplats(budget);
|
|
28533
|
+
entry.budget = budget;
|
|
28534
|
+
this.viewer.scene.requestRender();
|
|
28535
|
+
}
|
|
28536
|
+
if (entry.nodeBudget !== nodeBudget && typeof entry.object.setMaxNodeSplats === "function") {
|
|
28537
|
+
entry.object.setMaxNodeSplats(nodeBudget);
|
|
28538
|
+
entry.nodeBudget = nodeBudget;
|
|
28539
|
+
this.viewer.scene.requestRender();
|
|
28540
|
+
}
|
|
28541
|
+
}
|
|
28542
|
+
}
|
|
28543
|
+
/*
|
|
28544
|
+
* Restores the scan's visibility method and releases unused listeners.
|
|
28545
|
+
*/
|
|
28546
|
+
Remove(object) {
|
|
28547
|
+
const entry = this.entries.find(entry => entry.object === object);
|
|
28548
|
+
if (entry) {
|
|
28549
|
+
object.setVisible = entry.setVisible;
|
|
28550
|
+
this.entries = this.entries.filter(other => other !== entry);
|
|
28551
|
+
this.lastUpdate = -Infinity;
|
|
28552
|
+
this.lastAllocation = -Infinity;
|
|
28553
|
+
}
|
|
28554
|
+
if (!this.entries.length) {
|
|
28555
|
+
this.Dispose();
|
|
28556
|
+
}
|
|
28557
|
+
}
|
|
28558
|
+
/*
|
|
28559
|
+
* Restores visibility intent and releases all controller listeners.
|
|
28560
|
+
*/
|
|
28561
|
+
Dispose() {
|
|
28562
|
+
this.removals.forEach(remove => remove());
|
|
28563
|
+
this.removals = [];
|
|
28564
|
+
this.entries.forEach(entry => {
|
|
28565
|
+
entry.object.setVisible = entry.setVisible;
|
|
28566
|
+
try {
|
|
28567
|
+
if (entry.visible !== entry.wantedVisible && typeof entry.setVisible === "function") {
|
|
28568
|
+
entry.setVisible.call(entry.object, entry.wantedVisible);
|
|
28569
|
+
}
|
|
28570
|
+
}
|
|
28571
|
+
catch {
|
|
28572
|
+
// A disposed or replaced optional SDK must not break viewer cleanup.
|
|
28573
|
+
}
|
|
28574
|
+
});
|
|
28575
|
+
this.entries = [];
|
|
28576
|
+
if (this.viewer["_nextspaceXGridsLod"] === this) {
|
|
28577
|
+
delete this.viewer["_nextspaceXGridsLod"];
|
|
28578
|
+
}
|
|
28579
|
+
}
|
|
28580
|
+
}
|
|
28581
|
+
XGridsRenderEngine.AdaptiveLod = AdaptiveLod;
|
|
28231
28582
|
/**
|
|
28232
28583
|
* Applies position, rotation, and scale to a live XGrids render object.
|
|
28233
28584
|
*/
|
|
@@ -49474,88 +49825,103 @@
|
|
|
49474
49825
|
});
|
|
49475
49826
|
cEntity.show = true;
|
|
49476
49827
|
}
|
|
49477
|
-
const
|
|
49478
|
-
|
|
49479
|
-
|
|
49480
|
-
|
|
49481
|
-
|
|
49482
|
-
|
|
49483
|
-
|
|
49484
|
-
|
|
49485
|
-
|
|
49486
|
-
|
|
49487
|
-
|
|
49488
|
-
|
|
49489
|
-
|
|
49490
|
-
|
|
49828
|
+
const model = cEntity.model;
|
|
49829
|
+
model._radiusLoaded = false;
|
|
49830
|
+
/*
|
|
49831
|
+
* Retains bounds measurement for hosts that cannot expose the displayed model.
|
|
49832
|
+
*/
|
|
49833
|
+
const measureTemporaryModelBounds = () => {
|
|
49834
|
+
const fileRadiusKey = `model3d_${BModels.UrlUtils.RemoveSignature(params.lodUrl)}_${scale * styleScale}_radius`;
|
|
49835
|
+
let heightProm = _fileRadiusCache.Get(fileRadiusKey);
|
|
49836
|
+
if (!heightProm) {
|
|
49837
|
+
heightProm = new Promise(async (res) => {
|
|
49838
|
+
try {
|
|
49839
|
+
// The fallback needs a temporary primitive until its bounds become available.
|
|
49840
|
+
const modelPrim = await getModelEntity(params.lodUrl, scale * styleScale);
|
|
49841
|
+
/*
|
|
49842
|
+
* Copies bounds before releasing the temporary primitive.
|
|
49843
|
+
*/
|
|
49844
|
+
const onReady = () => {
|
|
49845
|
+
readyEventRemoval === null || readyEventRemoval === void 0 ? void 0 : readyEventRemoval();
|
|
49846
|
+
readyEventRemoval = null;
|
|
49847
|
+
/*
|
|
49848
|
+
* Releases the temporary primitive even if the viewer was destroyed.
|
|
49849
|
+
*/
|
|
49850
|
+
const kill = () => {
|
|
49851
|
+
if (params.viewer && !params.viewer.isDestroyed() && params.viewer.scene.primitives.contains(modelPrim)) {
|
|
49852
|
+
params.viewer.scene.primitives.remove(modelPrim);
|
|
49853
|
+
}
|
|
49854
|
+
if (!modelPrim.isDestroyed()) {
|
|
49855
|
+
modelPrim.destroy();
|
|
49856
|
+
}
|
|
49857
|
+
};
|
|
49858
|
+
if (!cEntity || !(modelPrim === null || modelPrim === void 0 ? void 0 : modelPrim.boundingSphere)) {
|
|
49859
|
+
kill();
|
|
49860
|
+
res(null);
|
|
49861
|
+
return;
|
|
49491
49862
|
}
|
|
49492
|
-
|
|
49493
|
-
|
|
49863
|
+
let radius = modelPrim.boundingSphere.radius;
|
|
49864
|
+
let centerOffset = modelPrim.boundingSphere.center;
|
|
49865
|
+
const bounds = {
|
|
49866
|
+
center: centerOffset ? Cesium.Cartesian3.clone(centerOffset) : Cesium.Cartesian3.ZERO.clone(),
|
|
49867
|
+
radius: modelPrim.boundingSphere.radius
|
|
49868
|
+
};
|
|
49869
|
+
if (centerOffset) {
|
|
49870
|
+
// Include the offset so origin-based culling contains the full model.
|
|
49871
|
+
const magnitude = Cesium.Cartesian3.magnitude(centerOffset);
|
|
49872
|
+
radius += magnitude;
|
|
49873
|
+
// Preserve extra culling padding for models with large origin offsets.
|
|
49874
|
+
if (magnitude > 100) {
|
|
49875
|
+
radius += 100;
|
|
49876
|
+
}
|
|
49494
49877
|
}
|
|
49495
|
-
};
|
|
49496
|
-
if (!cEntity || !(modelPrim === null || modelPrim === void 0 ? void 0 : modelPrim.boundingSphere)) {
|
|
49497
49878
|
kill();
|
|
49498
|
-
res(
|
|
49499
|
-
return;
|
|
49500
|
-
}
|
|
49501
|
-
let radius = modelPrim.boundingSphere.radius;
|
|
49502
|
-
let centerOffset = modelPrim.boundingSphere.center;
|
|
49503
|
-
const bounds = {
|
|
49504
|
-
center: centerOffset ? Cesium.Cartesian3.clone(centerOffset) : Cesium.Cartesian3.ZERO.clone(),
|
|
49505
|
-
radius: modelPrim.boundingSphere.radius
|
|
49879
|
+
res({ radius, bounds });
|
|
49506
49880
|
};
|
|
49507
|
-
|
|
49508
|
-
|
|
49509
|
-
|
|
49510
|
-
|
|
49511
|
-
|
|
49512
|
-
|
|
49513
|
-
|
|
49514
|
-
|
|
49515
|
-
|
|
49881
|
+
let readyEventRemoval = null;
|
|
49882
|
+
// Prefer the ready event when the host exposes it.
|
|
49883
|
+
if (modelPrim["readyEvent"]) {
|
|
49884
|
+
modelPrim["readyEvent"].addEventListener(onReady);
|
|
49885
|
+
}
|
|
49886
|
+
// Retain compatibility with promise-based hosts.
|
|
49887
|
+
else if (modelPrim["readyPromise"]) {
|
|
49888
|
+
modelPrim["readyPromise"].then(() => {
|
|
49889
|
+
onReady();
|
|
49890
|
+
}).catch((e) => {
|
|
49891
|
+
console.error(e);
|
|
49892
|
+
res(null);
|
|
49893
|
+
});
|
|
49516
49894
|
}
|
|
49517
|
-
|
|
49518
|
-
|
|
49519
|
-
|
|
49520
|
-
|
|
49521
|
-
|
|
49522
|
-
|
|
49523
|
-
|
|
49524
|
-
|
|
49525
|
-
|
|
49526
|
-
|
|
49527
|
-
|
|
49528
|
-
|
|
49529
|
-
|
|
49530
|
-
|
|
49531
|
-
|
|
49532
|
-
|
|
49895
|
+
params.viewer.scene.primitives.add(modelPrim);
|
|
49896
|
+
}
|
|
49897
|
+
catch (e) {
|
|
49898
|
+
console.error(e);
|
|
49899
|
+
res(null);
|
|
49900
|
+
}
|
|
49901
|
+
});
|
|
49902
|
+
_fileRadiusCache.Set(fileRadiusKey, heightProm);
|
|
49903
|
+
}
|
|
49904
|
+
heightProm.then((measured) => {
|
|
49905
|
+
if (model) {
|
|
49906
|
+
model._radius = measured ? measured.radius : null;
|
|
49907
|
+
model._bounds = measured ? measured.bounds : null;
|
|
49908
|
+
model._radiusLoaded = true;
|
|
49909
|
+
if (params.viewer && params.viewer.scene && !params.viewer.isDestroyed()) {
|
|
49910
|
+
exports.VisualRegisterCuller.MarkShouldRecheck(params.viewer);
|
|
49533
49911
|
}
|
|
49534
|
-
params.viewer.scene.primitives.add(modelPrim);
|
|
49535
49912
|
}
|
|
49536
|
-
|
|
49537
|
-
|
|
49538
|
-
|
|
49913
|
+
// Rough estimate on when the model is ready in the scene.
|
|
49914
|
+
if (animateScale) {
|
|
49915
|
+
animateScale.Play();
|
|
49539
49916
|
}
|
|
49540
49917
|
});
|
|
49541
|
-
|
|
49918
|
+
};
|
|
49919
|
+
if (Cesium.Model.fromGltfAsync) {
|
|
49920
|
+
trackRenderedModelBounds(params.viewer, cEntity, model, scale * styleScale, measureTemporaryModelBounds, animateScale);
|
|
49921
|
+
}
|
|
49922
|
+
else {
|
|
49923
|
+
measureTemporaryModelBounds();
|
|
49542
49924
|
}
|
|
49543
|
-
heightProm.then((measured) => {
|
|
49544
|
-
if (model) {
|
|
49545
|
-
model._radius = measured ? measured.radius : null;
|
|
49546
|
-
model._bounds = measured ? measured.bounds : null;
|
|
49547
|
-
model._radiusLoaded = true;
|
|
49548
|
-
if (params.viewer && params.viewer.scene && !params.viewer.isDestroyed()) {
|
|
49549
|
-
exports.VisualRegisterCuller.MarkShouldRecheck(params.viewer);
|
|
49550
|
-
}
|
|
49551
|
-
}
|
|
49552
|
-
// Rough estimate on when the model is ready in the scene.
|
|
49553
|
-
if (animateScale) {
|
|
49554
|
-
animateScale.Play();
|
|
49555
|
-
}
|
|
49556
|
-
});
|
|
49557
|
-
const model = cEntity.model;
|
|
49558
|
-
model._radiusLoaded = false;
|
|
49559
49925
|
model._clientFileId = params.lodClientFileId;
|
|
49560
49926
|
model._entityScale = {
|
|
49561
49927
|
record: scale,
|
|
@@ -49763,6 +50129,88 @@
|
|
|
49763
50129
|
}
|
|
49764
50130
|
EntityRenderEngineModel3d.RenderGroup = RenderGroup;
|
|
49765
50131
|
})(exports.EntityRenderEngineModel3d || (exports.EntityRenderEngineModel3d = {}));
|
|
50132
|
+
/*
|
|
50133
|
+
* Measures bounds from Cesium's displayed model so loading a visual does not also load a temporary model.
|
|
50134
|
+
*/
|
|
50135
|
+
function trackRenderedModelBounds(viewer, entity, model, targetScale, fallback, animateScale) {
|
|
50136
|
+
const key = "_nextspaceRenderedModelBoundsMonitor";
|
|
50137
|
+
let monitor = viewer[key];
|
|
50138
|
+
if (!monitor) {
|
|
50139
|
+
monitor = { pending: new Map() };
|
|
50140
|
+
viewer[key] = monitor;
|
|
50141
|
+
}
|
|
50142
|
+
monitor.pending.set(entity.id, { entity, model, targetScale, fallback, animateScale });
|
|
50143
|
+
if (monitor.removeListener) {
|
|
50144
|
+
return;
|
|
50145
|
+
}
|
|
50146
|
+
monitor.removeListener = viewer.scene.postRender.addEventListener(() => {
|
|
50147
|
+
var _a, _b, _c, _d, _e, _f;
|
|
50148
|
+
if (viewer.isDestroyed()) {
|
|
50149
|
+
monitor.pending.clear();
|
|
50150
|
+
}
|
|
50151
|
+
else {
|
|
50152
|
+
const primitives = viewer.scene.primitives;
|
|
50153
|
+
for (let i = 0; i < primitives.length && monitor.pending.size; i++) {
|
|
50154
|
+
const primitive = primitives.get(i);
|
|
50155
|
+
if (!(primitive instanceof Cesium.Model) || !primitive.ready) {
|
|
50156
|
+
continue;
|
|
50157
|
+
}
|
|
50158
|
+
const task = monitor.pending.get((_a = primitive.id) === null || _a === void 0 ? void 0 : _a.id);
|
|
50159
|
+
if (!task || primitive.id !== task.entity || task.entity.model !== task.model) {
|
|
50160
|
+
continue;
|
|
50161
|
+
}
|
|
50162
|
+
try {
|
|
50163
|
+
const sphere = primitive.boundingSphere;
|
|
50164
|
+
const matrix = primitive.heightReference == null || primitive.heightReference === Cesium.HeightReference.NONE
|
|
50165
|
+
? primitive.modelMatrix
|
|
50166
|
+
: primitive._clampedModelMatrix;
|
|
50167
|
+
if (!sphere || !matrix ||
|
|
50168
|
+
!Number.isFinite(sphere.radius) || sphere.radius < 0 ||
|
|
50169
|
+
!Number.isFinite((_b = sphere.center) === null || _b === void 0 ? void 0 : _b.x) ||
|
|
50170
|
+
!Number.isFinite((_c = sphere.center) === null || _c === void 0 ? void 0 : _c.y) ||
|
|
50171
|
+
!Number.isFinite((_d = sphere.center) === null || _d === void 0 ? void 0 : _d.z)) {
|
|
50172
|
+
throw new Error("Displayed model bounds unavailable");
|
|
50173
|
+
}
|
|
50174
|
+
const inverse = Cesium.Matrix4.inverseTransformation(matrix, new Cesium.Matrix4());
|
|
50175
|
+
const center = Cesium.Matrix4.multiplyByPoint(inverse, sphere.center, new Cesium.Cartesian3());
|
|
50176
|
+
const scaleRatio = task.targetScale / primitive.scale;
|
|
50177
|
+
Cesium.Cartesian3.multiplyByScalar(center, scaleRatio, center);
|
|
50178
|
+
const radius = sphere.radius * scaleRatio;
|
|
50179
|
+
const magnitude = Cesium.Cartesian3.magnitude(center);
|
|
50180
|
+
if (!Number.isFinite(scaleRatio) || scaleRatio <= 0 || !Number.isFinite(magnitude) || !Number.isFinite(radius)) {
|
|
50181
|
+
throw new Error("Displayed model bounds transform invalid");
|
|
50182
|
+
}
|
|
50183
|
+
task.model._bounds = { center, radius };
|
|
50184
|
+
task.model._radius = radius + magnitude + (magnitude > 100 ? 100 : 0);
|
|
50185
|
+
task.model._radiusLoaded = true;
|
|
50186
|
+
(_e = task.animateScale) === null || _e === void 0 ? void 0 : _e.Play();
|
|
50187
|
+
exports.VisualRegisterCuller.MarkShouldRecheck(viewer);
|
|
50188
|
+
}
|
|
50189
|
+
catch (e) {
|
|
50190
|
+
task.fallback();
|
|
50191
|
+
}
|
|
50192
|
+
monitor.pending.delete(task.entity.id);
|
|
50193
|
+
}
|
|
50194
|
+
for (const [id, task] of monitor.pending) {
|
|
50195
|
+
const modelShown = GetCValue(viewer, task.model.show) !== false;
|
|
50196
|
+
if (!task.entity.isShowing || !modelShown) {
|
|
50197
|
+
task.visibleAt = null;
|
|
50198
|
+
}
|
|
50199
|
+
else if (task.visibleAt == null) {
|
|
50200
|
+
task.visibleAt = performance.now();
|
|
50201
|
+
}
|
|
50202
|
+
else if (performance.now() - task.visibleAt > 60000) {
|
|
50203
|
+
task.fallback();
|
|
50204
|
+
monitor.pending.delete(id);
|
|
50205
|
+
}
|
|
50206
|
+
}
|
|
50207
|
+
}
|
|
50208
|
+
if (!monitor.pending.size) {
|
|
50209
|
+
(_f = monitor.removeListener) === null || _f === void 0 ? void 0 : _f.call(monitor);
|
|
50210
|
+
monitor.removeListener = null;
|
|
50211
|
+
}
|
|
50212
|
+
});
|
|
50213
|
+
}
|
|
49766
50214
|
async function getName$1(api, entity, offline) {
|
|
49767
50215
|
var _a;
|
|
49768
50216
|
const ownName = GetUsableEntityName(entity);
|
|
@@ -57115,7 +57563,7 @@ void main() {
|
|
|
57115
57563
|
StyleUtils.ApplyTypeStyle = ApplyTypeStyle;
|
|
57116
57564
|
})(exports.StyleUtils || (exports.StyleUtils = {}));
|
|
57117
57565
|
|
|
57118
|
-
const VERSION = "7.7.
|
|
57566
|
+
const VERSION = "7.7.5";
|
|
57119
57567
|
/**
|
|
57120
57568
|
* Updates the environment instance used by bruce-cesium to one specified.
|
|
57121
57569
|
* This can be used to ensure that the instance a parent is referencing is shared between bruce-cesium, bruce-models, and the parent app.
|