s3m-three 0.4.19 → 0.4.21
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/browser/assets/{s3mWorker-4iTAmWIu.js → s3mWorker-DvAUA8NJ.js} +1 -1
- package/dist/browser/s3m-three.iife.ext-three.js +243 -243
- package/dist/browser/s3m-three.iife.js +227 -227
- package/dist/core/Draco.d.ts.map +1 -1
- package/dist/core/Draco.js +0 -1
- package/dist/core/Draco.js.map +1 -1
- package/dist/core/S3MBlockParser.d.ts.map +1 -1
- package/dist/core/S3MBlockParser.js +27 -14
- package/dist/core/S3MBlockParser.js.map +1 -1
- package/dist/core/SplatSort.d.ts +14 -1
- package/dist/core/SplatSort.d.ts.map +1 -1
- package/dist/core/SplatSort.js +51 -4
- package/dist/core/SplatSort.js.map +1 -1
- package/dist/core/TileGeometry.d.ts +10 -0
- package/dist/core/TileGeometry.d.ts.map +1 -1
- package/dist/core/TileGeometry.js +17 -14
- package/dist/core/TileGeometry.js.map +1 -1
- package/dist/render/DatasetManager.d.ts +3 -1
- package/dist/render/DatasetManager.d.ts.map +1 -1
- package/dist/render/DatasetManager.js +2 -1
- package/dist/render/DatasetManager.js.map +1 -1
- package/dist/render/FeatureStyleManager.d.ts.map +1 -1
- package/dist/render/GeometryBuilder.d.ts +8 -0
- package/dist/render/GeometryBuilder.d.ts.map +1 -1
- package/dist/render/GeometryBuilder.js +62 -7
- package/dist/render/GeometryBuilder.js.map +1 -1
- package/dist/render/S3MViewer.d.ts +106 -440
- package/dist/render/S3MViewer.d.ts.map +1 -1
- package/dist/render/S3MViewer.js +297 -1653
- package/dist/render/S3MViewer.js.map +1 -1
- package/dist/render/SplatSorter.d.ts.map +1 -1
- package/dist/render/SplatSorter.js +8 -1
- package/dist/render/SplatSorter.js.map +1 -1
- package/dist/render/viewer/EdgeDecorator.d.ts +206 -0
- package/dist/render/viewer/EdgeDecorator.d.ts.map +1 -0
- package/dist/render/viewer/EdgeDecorator.js +628 -0
- package/dist/render/viewer/EdgeDecorator.js.map +1 -0
- package/dist/render/viewer/HeightIndex.d.ts +36 -0
- package/dist/render/viewer/HeightIndex.d.ts.map +1 -0
- package/dist/render/viewer/HeightIndex.js +98 -0
- package/dist/render/viewer/HeightIndex.js.map +1 -0
- package/dist/render/viewer/LightRig.d.ts +88 -0
- package/dist/render/viewer/LightRig.d.ts.map +1 -0
- package/dist/render/viewer/LightRig.js +229 -0
- package/dist/render/viewer/LightRig.js.map +1 -0
- package/dist/render/viewer/PickService.d.ts +109 -0
- package/dist/render/viewer/PickService.d.ts.map +1 -0
- package/dist/render/viewer/PickService.js +591 -0
- package/dist/render/viewer/PickService.js.map +1 -0
- package/dist/render/viewer/SelectionDecorator.d.ts +84 -0
- package/dist/render/viewer/SelectionDecorator.d.ts.map +1 -0
- package/dist/render/viewer/SelectionDecorator.js +339 -0
- package/dist/render/viewer/SelectionDecorator.js.map +1 -0
- package/dist/render/viewer/SplatLayer.d.ts +26 -0
- package/dist/render/viewer/SplatLayer.d.ts.map +1 -0
- package/dist/render/viewer/SplatLayer.js +44 -0
- package/dist/render/viewer/SplatLayer.js.map +1 -0
- package/dist/render/viewer/types.d.ts +256 -0
- package/dist/render/viewer/types.d.ts.map +1 -0
- package/dist/render/viewer/types.js +3 -0
- package/dist/render/viewer/types.js.map +1 -0
- package/dist/tileset/S3MTileset.d.ts +30 -3
- package/dist/tileset/S3MTileset.d.ts.map +1 -1
- package/dist/tileset/S3MTileset.js +99 -5
- package/dist/tileset/S3MTileset.js.map +1 -1
- package/dist/worker/s3mWorker.js +1 -1
- package/dist/worker/s3mWorker.js.map +1 -1
- package/docs/API.md +9 -28
- package/docs/FORMAT-NOTES.md +38 -14
- package/package.json +1 -1
- package/src/core/Draco.ts +1 -2
- package/src/core/S3MBlockParser.ts +27 -16
- package/src/core/SplatSort.ts +67 -5
- package/src/core/TileGeometry.ts +24 -11
- package/src/render/DatasetManager.ts +5 -1
- package/src/render/FeatureStyleManager.ts +1 -1
- package/src/render/GeometryBuilder.ts +59 -7
- package/src/render/S3MViewer.ts +327 -1916
- package/src/render/SplatSorter.ts +8 -1
- package/src/render/viewer/EdgeDecorator.ts +722 -0
- package/src/render/viewer/HeightIndex.ts +94 -0
- package/src/render/viewer/LightRig.ts +267 -0
- package/src/render/viewer/PickService.ts +651 -0
- package/src/render/viewer/SelectionDecorator.ts +377 -0
- package/src/render/viewer/SplatLayer.ts +44 -0
- package/src/render/viewer/types.ts +264 -0
- package/src/tileset/S3MTileset.ts +106 -6
|
@@ -233,7 +233,7 @@ export interface TileNode {
|
|
|
233
233
|
/** 该瓦片引用的纹理 key 清单,用于引用计数与显存释放 */
|
|
234
234
|
textureKeys?: string[];
|
|
235
235
|
/** 瓦片构建产生的统计信息,用于淘汰时准确扣减 stats */
|
|
236
|
-
stats?: { meshes: number; vertices: number; triangles: number };
|
|
236
|
+
stats?: { meshes: number; vertices: number; triangles: number; memory?: number };
|
|
237
237
|
}
|
|
238
238
|
|
|
239
239
|
/** 瓦片构建器可注入,用于测试 / 服务端渲染(此时不需要 three) */
|
|
@@ -287,6 +287,14 @@ export interface S3MTilesetOptions {
|
|
|
287
287
|
* 不传 = 不限制,行为与旧版完全一致。运行时可用 `setMaxTriangles()` 调整。
|
|
288
288
|
*/
|
|
289
289
|
maxTriangles?: number;
|
|
290
|
+
/**
|
|
291
|
+
* 本数据集**驻留显存/内存字节数**的软上限(默认不限制)。
|
|
292
|
+
* 包含几何顶点缓冲(精确字节)与纹理显存估计。超限时按同一套 make-before-break
|
|
293
|
+
* 主动淘汰非显示瓦片及其独占纹理。
|
|
294
|
+
*
|
|
295
|
+
* 不传 = 不限制(Infinity),行为与旧版完全一致。运行时可用 `setMaxMemory()` 调整。
|
|
296
|
+
*/
|
|
297
|
+
maxMemory?: number;
|
|
290
298
|
/**
|
|
291
299
|
* 是否请求 `.texblock` 子图集(S3MBLOCK 根图集的清晰版)。**默认关**。
|
|
292
300
|
*
|
|
@@ -315,6 +323,54 @@ export interface S3MTilesetOptions {
|
|
|
315
323
|
unsupported?: UnsupportedPolicy;
|
|
316
324
|
}
|
|
317
325
|
|
|
326
|
+
/** 估算单个纹理占用的显存字节数 */
|
|
327
|
+
export function estimateTextureBytes(tex: any): number {
|
|
328
|
+
if (!tex) return 0;
|
|
329
|
+
if (Array.isArray(tex.mipmaps) && tex.mipmaps.length > 0) {
|
|
330
|
+
let bytes = 0;
|
|
331
|
+
for (const m of tex.mipmaps) {
|
|
332
|
+
if (m?.data?.byteLength) bytes += m.data.byteLength;
|
|
333
|
+
}
|
|
334
|
+
if (bytes > 0) return bytes;
|
|
335
|
+
}
|
|
336
|
+
const img = tex.image;
|
|
337
|
+
if (!img) return 0;
|
|
338
|
+
if (img.data && typeof img.data.byteLength === 'number') {
|
|
339
|
+
return img.data.byteLength;
|
|
340
|
+
}
|
|
341
|
+
const w = img.width ?? 0;
|
|
342
|
+
const h = img.height ?? 0;
|
|
343
|
+
if (w > 0 && h > 0) {
|
|
344
|
+
const factor = tex.generateMipmaps ? 1.3333333333333333 : 1;
|
|
345
|
+
return Math.round(w * h * 4 * factor);
|
|
346
|
+
}
|
|
347
|
+
return 0;
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
/** 估算三维对象树中包含的几何缓冲字节数 */
|
|
351
|
+
export function estimateObjectGeometryBytes(obj: any): number {
|
|
352
|
+
let bytes = 0;
|
|
353
|
+
if (!obj) return 0;
|
|
354
|
+
obj.traverse?.((child: any) => {
|
|
355
|
+
const geo = child.geometry;
|
|
356
|
+
if (geo) {
|
|
357
|
+
if (geo.attributes) {
|
|
358
|
+
for (const attr of Object.values(geo.attributes) as any[]) {
|
|
359
|
+
if (attr?.array?.byteLength) bytes += attr.array.byteLength;
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
if (geo.index?.array?.byteLength) {
|
|
363
|
+
bytes += geo.index.array.byteLength;
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
if (child.isInstancedMesh) {
|
|
367
|
+
if (child.instanceMatrix?.array?.byteLength) bytes += child.instanceMatrix.array.byteLength;
|
|
368
|
+
if (child.instanceColor?.array?.byteLength) bytes += child.instanceColor.array.byteLength;
|
|
369
|
+
}
|
|
370
|
+
});
|
|
371
|
+
return bytes;
|
|
372
|
+
}
|
|
373
|
+
|
|
318
374
|
export class S3MTileset {
|
|
319
375
|
configUrl: string;
|
|
320
376
|
config: Record<string, unknown> | null = null;
|
|
@@ -377,6 +433,10 @@ export class S3MTileset {
|
|
|
377
433
|
* 判据与旧版逐字一致,不会多算一次面数。
|
|
378
434
|
*/
|
|
379
435
|
maxTriangles: number;
|
|
436
|
+
/**
|
|
437
|
+
* 驻留显存/内存字节数的软上限。`Infinity` = 不限制(默认)。
|
|
438
|
+
*/
|
|
439
|
+
maxMemory: number;
|
|
380
440
|
lodRangeScale: number;
|
|
381
441
|
|
|
382
442
|
/** 数据集配置声明的高度范围(米),若配置未声明则返回 null */
|
|
@@ -403,7 +463,6 @@ export class S3MTileset {
|
|
|
403
463
|
/** 子瓦片 URL → 父瓦片 URL,用于淘汰后补洞 */
|
|
404
464
|
private readonly _parentOf = new Map<string, string>();
|
|
405
465
|
private _frame = 0;
|
|
406
|
-
private _lodDbgOnce = false;
|
|
407
466
|
/** 格式类永久错误只向上报一次,避免整棵瓦片树刷同样的日志 */
|
|
408
467
|
private _permanentReported = false;
|
|
409
468
|
/** 请求量的硬上限(软上限 maxTiles 的超额余量),见构造函数注释 */
|
|
@@ -440,6 +499,9 @@ export class S3MTileset {
|
|
|
440
499
|
this.maxConcurrent = options.maxConcurrent ?? 4;
|
|
441
500
|
this.maxTiles = options.maxTiles ?? 64;
|
|
442
501
|
this.maxTriangles = options.maxTriangles ?? Infinity;
|
|
502
|
+
this.maxMemory = Number.isFinite(options.maxMemory) && (options.maxMemory as number) > 0
|
|
503
|
+
? (options.maxMemory as number)
|
|
504
|
+
: Infinity;
|
|
443
505
|
this.maxImageCache = options.maxImageCache ?? 128;
|
|
444
506
|
// 硬上限 = 软上限 + 余量。淘汰只在「新瓦片已经落地并接管显示」之后做(make-before-break),
|
|
445
507
|
// 所以中间态允许临时超出 maxTiles;硬上限只用来挡住失控的请求量,不用于挤掉正在显示的内容。
|
|
@@ -652,14 +714,49 @@ export class S3MTileset {
|
|
|
652
714
|
this.maxTriangles = n > 0 ? n : Infinity;
|
|
653
715
|
}
|
|
654
716
|
|
|
717
|
+
/**
|
|
718
|
+
* 运行时调整显存/内存字节预算。`Infinity` = 不限制(默认)。
|
|
719
|
+
* 收紧后不会立刻掉内容,要等下一次 `_trimBudget`(下一帧 update)才生效。
|
|
720
|
+
*/
|
|
721
|
+
setMaxMemory(bytes: number): void {
|
|
722
|
+
this.maxMemory = Number.isFinite(bytes) && bytes > 0 ? bytes : Infinity;
|
|
723
|
+
}
|
|
724
|
+
|
|
725
|
+
/**
|
|
726
|
+
* 当前数据集驻留的显存与内存总字节数(几何缓冲精确大小 + 纹理显存估计)
|
|
727
|
+
*/
|
|
728
|
+
residentMemory(): number {
|
|
729
|
+
return this._residentGeometryBytes() + this._residentTextureBytes();
|
|
730
|
+
}
|
|
731
|
+
|
|
732
|
+
private _residentGeometryBytes(): number {
|
|
733
|
+
let total = 0;
|
|
734
|
+
for (const node of this.nodes.values()) {
|
|
735
|
+
if (node.stats && typeof node.stats.memory === 'number') {
|
|
736
|
+
total += node.stats.memory;
|
|
737
|
+
} else if (node.group) {
|
|
738
|
+
total += estimateObjectGeometryBytes(node.group);
|
|
739
|
+
}
|
|
740
|
+
}
|
|
741
|
+
return total;
|
|
742
|
+
}
|
|
743
|
+
|
|
744
|
+
private _residentTextureBytes(): number {
|
|
745
|
+
let total = 0;
|
|
746
|
+
for (const tex of this.textureCache.values()) {
|
|
747
|
+
total += estimateTextureBytes(tex);
|
|
748
|
+
}
|
|
749
|
+
return total;
|
|
750
|
+
}
|
|
751
|
+
|
|
655
752
|
/**
|
|
656
753
|
* 预算裁剪 —— 必须在可见性算完之后调用(make-before-break):
|
|
657
754
|
* 新瓦片已经落地、也已经决定由谁负责显示,这时候才把没人依赖的那块裁掉。
|
|
658
755
|
* 只踢「当前不显示」或「位置已被可见子瓦接手」的瓦片;挑不出安全候选时允许
|
|
659
756
|
* 暂时超出预算,等下一帧再裁 —— 宁可多占一会儿内存,也不在画面上开洞。
|
|
660
757
|
*
|
|
661
|
-
*
|
|
662
|
-
* `maxTriangles` 为 Infinity 时短路,行为与只有瓦片数预算时完全一致。
|
|
758
|
+
* 三条预算并行:瓦片数(`maxTiles`)、三角形总数(`maxTriangles`)与显存字节(`maxMemory`)。
|
|
759
|
+
* `maxTriangles` / `maxMemory` 为 Infinity 时短路,行为与只有瓦片数预算时完全一致。
|
|
663
760
|
*/
|
|
664
761
|
private _trimBudget(): boolean {
|
|
665
762
|
let removed = false;
|
|
@@ -668,9 +765,11 @@ export class S3MTileset {
|
|
|
668
765
|
const overTiles = () => this.nodes.size + this.pending.size > this.maxTiles;
|
|
669
766
|
const overTriangles = () =>
|
|
670
767
|
Number.isFinite(this.maxTriangles) && this._residentTriangles() > this.maxTriangles;
|
|
671
|
-
|
|
768
|
+
const overMemory = () =>
|
|
769
|
+
Number.isFinite(this.maxMemory) && this.residentMemory() > this.maxMemory;
|
|
770
|
+
// 预算生效时可能要连踢多块,迭代上限跟着驻留规模走;不生效时根本进不了循环
|
|
672
771
|
const iterationCap = this.nodes.size + this.maxTiles + 16;
|
|
673
|
-
while ((overTiles() || overTriangles()) && guard++ <= iterationCap) {
|
|
772
|
+
while ((overTiles() || overTriangles() || overMemory()) && guard++ <= iterationCap) {
|
|
674
773
|
if (!this._evictOne(this.nodes.size + this.pending.size > this.hardCap)) break;
|
|
675
774
|
removed = true;
|
|
676
775
|
}
|
|
@@ -1189,6 +1288,7 @@ export class S3MTileset {
|
|
|
1189
1288
|
meshes: stats.meshes ?? 0,
|
|
1190
1289
|
vertices: stats.vertices ?? 0,
|
|
1191
1290
|
triangles: stats.triangles ?? 0,
|
|
1291
|
+
memory: (stats as any).memory ?? estimateObjectGeometryBytes(group),
|
|
1192
1292
|
},
|
|
1193
1293
|
};
|
|
1194
1294
|
|