s3m-maplibre 0.1.0 → 0.2.4
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/README.md +2 -2
- package/dist/core/types.d.ts +27 -0
- package/dist/core/types.d.ts.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/render/GeometryBuilder.d.ts +7 -0
- package/dist/render/GeometryBuilder.d.ts.map +1 -1
- package/dist/render/GeometryBuilder.js +310 -18
- package/dist/render/GeometryBuilder.js.map +1 -1
- package/dist/render/S3MLayer.d.ts +84 -4
- package/dist/render/S3MLayer.d.ts.map +1 -1
- package/dist/render/S3MLayer.js +264 -9
- package/dist/render/S3MLayer.js.map +1 -1
- package/dist/render/StyleMaterial.d.ts +38 -0
- package/dist/render/StyleMaterial.d.ts.map +1 -1
- package/dist/render/StyleMaterial.js +150 -8
- package/dist/render/StyleMaterial.js.map +1 -1
- package/dist/vendor/meshopt_decoder.module.js +112 -112
- package/docs/API.md +0 -2
- package/package.json +87 -78
- package/src/core/S3MBParser.ts +586 -586
- package/src/core/types.ts +9 -0
- package/src/index.ts +4 -1
- package/src/render/GeometryBuilder.ts +354 -19
- package/src/render/S3MLayer.ts +328 -10
- package/src/render/StyleMaterial.ts +164 -8
- package/src/vendor/meshopt_decoder.module.js +112 -112
- package/tools/copy-assets.mjs +28 -0
- package/tools/e2e.mjs +78 -0
- package/tools/lod-probe.mjs +60 -0
- package/tools/meshopt-check.mjs +242 -0
- package/tools/official-oracle.mjs +54 -0
- package/tools/parse-sample.mjs +87 -0
- package/tools/serve.mjs +51 -0
- package/tools/test-batch-texmatrix.mjs +221 -0
- package/tools/trace-one.mjs +93 -0
package/README.md
CHANGED
|
@@ -45,6 +45,8 @@ iServer / 本地目录 → .scp 配置 + .s3mb 瓦片
|
|
|
45
45
|
| 全局棱线 | ✅ | 优先用数据自带棱线包,没有才 CPU 现算 |
|
|
46
46
|
| 单体级点选 + 属性 | ✅ | GPU 拾取,代价与面数无关 |
|
|
47
47
|
| 实例化几何 | ✅ | `instanceMode` 16 / 17 |
|
|
48
|
+
| 瓦片同材质合批 | ✅ | 倾斜摄影大瓦片自动合批,大幅降低 DrawCall |
|
|
49
|
+
| 纹理变换与寻址 | ✅ | 支持 `texmodmatrix` 仿射变换与 `addressmode` |
|
|
48
50
|
| DXT / WebP 纹理 | ✅ | |
|
|
49
51
|
| Draco 压缩几何 | ❌ | 遇到会抛明确错误 |
|
|
50
52
|
| KTX2 / CRN | ❌ | |
|
|
@@ -228,8 +230,6 @@ S3M 顶点(数据集局部 ENU,米)
|
|
|
228
230
|
|
|
229
231
|
- **Draco 压缩几何**未实现。MeshOpt 已支持;遇到 Draco 会抛带说明的错误。
|
|
230
232
|
- **地形遮挡**未实现:MapLibre 的地形深度没进 custom layer 的深度缓冲,建筑不会被地形裁掉。
|
|
231
|
-
- 每个 `indexPackage` 一个 `Mesh`,倾斜摄影大瓦片需要合批。
|
|
232
|
-
- `texmodmatrix`(纹理变换)未应用。
|
|
233
233
|
- 跨城市量级的数据集叠加会重新引入 float32 精度问题。
|
|
234
234
|
|
|
235
235
|
---
|
package/dist/core/types.d.ts
CHANGED
|
@@ -183,17 +183,44 @@ export interface StyleUniforms {
|
|
|
183
183
|
uDim: {
|
|
184
184
|
value: number;
|
|
185
185
|
};
|
|
186
|
+
uDimFactor?: {
|
|
187
|
+
value: number;
|
|
188
|
+
};
|
|
186
189
|
uSelColor: {
|
|
187
190
|
value: Color;
|
|
188
191
|
};
|
|
189
192
|
uSelMix: {
|
|
190
193
|
value: number;
|
|
191
194
|
};
|
|
195
|
+
uSelMode?: {
|
|
196
|
+
value: number;
|
|
197
|
+
};
|
|
198
|
+
uSelOpacity?: {
|
|
199
|
+
value: number;
|
|
200
|
+
};
|
|
201
|
+
uSelEmissive?: {
|
|
202
|
+
value: number;
|
|
203
|
+
};
|
|
204
|
+
uSelElevation?: {
|
|
205
|
+
value: number;
|
|
206
|
+
};
|
|
207
|
+
uFilterMinZ?: {
|
|
208
|
+
value: number;
|
|
209
|
+
};
|
|
210
|
+
uFilterMaxZ?: {
|
|
211
|
+
value: number;
|
|
212
|
+
};
|
|
213
|
+
uFilterHeightActive?: {
|
|
214
|
+
value: number;
|
|
215
|
+
};
|
|
192
216
|
uRoofThreshold?: {
|
|
193
217
|
value: number;
|
|
194
218
|
};
|
|
195
219
|
uTexMix?: {
|
|
196
220
|
value: number;
|
|
197
221
|
};
|
|
222
|
+
[key: string]: {
|
|
223
|
+
value: unknown;
|
|
224
|
+
} | undefined;
|
|
198
225
|
}
|
|
199
226
|
//# sourceMappingURL=types.d.ts.map
|
package/dist/core/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/core/types.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/core/types.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -15,8 +15,8 @@ export { resolveFeature, measureSegments, buildAttributes, DEFAULT_FLOOR_HEIGHT
|
|
|
15
15
|
export type { Vec3, BoundingBox, AttrDType, VertexAttribute, IndexPackage, VertexPackage, PickSegment, PickEntry, GeoPackageEntry, Geode, PageLOD, GroupNode, S3MTexture, ParsedTile, Anchor, Stats, FeatureAttributes, SegmentBox, StyleUniforms, } from './core/types.js';
|
|
16
16
|
export { S3MTileset } from './tileset/S3MTileset.js';
|
|
17
17
|
export type { TileNode, BuildTileFn, S3MTilesetOptions } from './tileset/S3MTileset.js';
|
|
18
|
-
export { S3MLayer, DEFAULT_STYLE, STYLE, STYLE_LABELS } from './render/S3MLayer.js';
|
|
19
|
-
export type { S3MLayerOptions, S3MStyle, S3MDatasetOptions, S3MDatasetEntry, PickResult, MapLike, MapMouseEventLike, } from './render/S3MLayer.js';
|
|
18
|
+
export { S3MLayer, DEFAULT_STYLE, STYLE, STYLE_LABELS, SELECT_MODE, SELECT_MODE_LABELS } from './render/S3MLayer.js';
|
|
19
|
+
export type { S3MLayerOptions, S3MStyle, SelectMode, FeatureStyle, S3MFilter, S3MDatasetOptions, S3MDatasetEntry, PickResult, MapLike, MapMouseEventLike, } from './render/S3MLayer.js';
|
|
20
20
|
export { buildTileObjects } from './render/GeometryBuilder.js';
|
|
21
21
|
export type { BuildTileOptions, BuildTileResult, TileBuildStats } from './render/GeometryBuilder.js';
|
|
22
22
|
export { createTexture, PixelFormat, setMaxAnisotropy } from './render/TextureFactory.js';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACtF,YAAY,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACpE,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,eAAe,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAG/G,YAAY,EACV,IAAI,EACJ,WAAW,EACX,SAAS,EACT,eAAe,EACf,YAAY,EACZ,aAAa,EACb,WAAW,EACX,SAAS,EACT,eAAe,EACf,KAAK,EACL,OAAO,EACP,SAAS,EACT,UAAU,EACV,UAAU,EACV,MAAM,EACN,KAAK,EACL,iBAAiB,EACjB,UAAU,EACV,aAAa,GACd,MAAM,iBAAiB,CAAC;AAGzB,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AACrD,YAAY,EAAE,QAAQ,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAGxF,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACtF,YAAY,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACpE,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,eAAe,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAG/G,YAAY,EACV,IAAI,EACJ,WAAW,EACX,SAAS,EACT,eAAe,EACf,YAAY,EACZ,aAAa,EACb,WAAW,EACX,SAAS,EACT,eAAe,EACf,KAAK,EACL,OAAO,EACP,SAAS,EACT,UAAU,EACV,UAAU,EACV,MAAM,EACN,KAAK,EACL,iBAAiB,EACjB,UAAU,EACV,aAAa,GACd,MAAM,iBAAiB,CAAC;AAGzB,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AACrD,YAAY,EAAE,QAAQ,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAGxF,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AACrH,YAAY,EACV,eAAe,EACf,QAAQ,EACR,UAAU,EACV,YAAY,EACZ,SAAS,EACT,iBAAiB,EACjB,eAAe,EACf,UAAU,EACV,OAAO,EACP,iBAAiB,GAClB,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AAC/D,YAAY,EAAE,gBAAgB,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAErG,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AAC1F,YAAY,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAEjE,OAAO,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAC9G,YAAY,EAAE,SAAS,EAAE,cAAc,EAAE,qBAAqB,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAEnH,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAC5C,YAAY,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAElD,OAAO,EAAE,QAAQ,IAAI,OAAO,EAAE,MAAM,sBAAsB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -15,7 +15,7 @@ export { resolveFeature, measureSegments, buildAttributes, DEFAULT_FLOOR_HEIGHT
|
|
|
15
15
|
// —— 瓦片层
|
|
16
16
|
export { S3MTileset } from './tileset/S3MTileset.js';
|
|
17
17
|
// —— 渲染层
|
|
18
|
-
export { S3MLayer, DEFAULT_STYLE, STYLE, STYLE_LABELS } from './render/S3MLayer.js';
|
|
18
|
+
export { S3MLayer, DEFAULT_STYLE, STYLE, STYLE_LABELS, SELECT_MODE, SELECT_MODE_LABELS } from './render/S3MLayer.js';
|
|
19
19
|
export { buildTileObjects } from './render/GeometryBuilder.js';
|
|
20
20
|
export { createTexture, PixelFormat, setMaxAnisotropy } from './render/TextureFactory.js';
|
|
21
21
|
export { createSharedUniforms, createStyledMaterial, createOutlineMaterial } from './render/StyleMaterial.js';
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,oCAAoC;AACpC,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAEtF,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,eAAe,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAyB/G,SAAS;AACT,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAGrD,SAAS;AACT,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,oCAAoC;AACpC,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAEtF,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,eAAe,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAyB/G,SAAS;AACT,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAGrD,SAAS;AACT,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAcrH,OAAO,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AAG/D,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AAG1F,OAAO,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAG9G,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAG5C,OAAO,EAAE,QAAQ,IAAI,OAAO,EAAE,MAAM,sBAAsB,CAAC"}
|
|
@@ -29,6 +29,8 @@ export interface TileBuildStats {
|
|
|
29
29
|
instanced: number;
|
|
30
30
|
/** 数据自带的棱线包(primitiveType 13)数量 */
|
|
31
31
|
edgeLines: number;
|
|
32
|
+
/** 合批前原有独立网格数 */
|
|
33
|
+
originalMeshes?: number;
|
|
32
34
|
/** 被跳过的东西,加载完可以直接在控制台看 */
|
|
33
35
|
skipped: string[];
|
|
34
36
|
}
|
|
@@ -39,6 +41,11 @@ export interface BuildTileOptions {
|
|
|
39
41
|
/** 是否显示数据自带的棱线包 */
|
|
40
42
|
edges?: boolean;
|
|
41
43
|
edgeColor?: THREE.ColorRepresentation;
|
|
44
|
+
/**
|
|
45
|
+
* 是否开启瓦片内同材质网格合批(默认 true)。
|
|
46
|
+
* 对倾斜摄影、大网格切片瓦片可减少 90%+ DrawCall,显著提高渲染帧率。
|
|
47
|
+
*/
|
|
48
|
+
batching?: boolean;
|
|
42
49
|
}
|
|
43
50
|
export interface BuildTileResult {
|
|
44
51
|
group: THREE.Group;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GeometryBuilder.d.ts","sourceRoot":"","sources":["../../src/render/GeometryBuilder.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAI/B,OAAO,KAAK,EAIV,UAAU,EACV,aAAa,EAEd,MAAM,kBAAkB,CAAC;AAI1B;;;;;;GAMG;AACH,eAAO,MAAM,cAAc,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"GeometryBuilder.d.ts","sourceRoot":"","sources":["../../src/render/GeometryBuilder.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAI/B,OAAO,KAAK,EAIV,UAAU,EACV,aAAa,EAEd,MAAM,kBAAkB,CAAC;AAI1B;;;;;;GAMG;AACH,eAAO,MAAM,cAAc,KAAK,CAAC;AA+KjC,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,mCAAmC;IACnC,SAAS,EAAE,MAAM,CAAC;IAClB,iBAAiB;IACjB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,0BAA0B;IAC1B,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,MAAM,WAAW,gBAAgB;IAC/B,8CAA8C;IAC9C,QAAQ,CAAC,EAAE,aAAa,CAAC;IACzB,YAAY,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;IAC1C,mBAAmB;IACnB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,SAAS,CAAC,EAAE,KAAK,CAAC,mBAAmB,CAAC;IACtC;;;OAGG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC;IACnB,KAAK,EAAE,cAAc,CAAC;IACtB,OAAO,EAAE,KAAK,CAAC,QAAQ,EAAE,CAAC;CAC3B;AAYD,wBAAsB,gBAAgB,CACpC,IAAI,EAAE,UAAU,EAChB,OAAO,GAAE,gBAAqB,GAC7B,OAAO,CAAC,eAAe,CAAC,CA0iB1B"}
|
|
@@ -56,21 +56,24 @@ function typedArrayOf(dtype, length) {
|
|
|
56
56
|
}
|
|
57
57
|
}
|
|
58
58
|
function toBufferAttribute(attr) {
|
|
59
|
-
const { data,
|
|
59
|
+
const { data, stride, offsetInBytes, dtype = 'f32' } = attr;
|
|
60
|
+
const components = attr.components ?? attr.comp ?? 3;
|
|
60
61
|
const bpe = bytesPerElement(dtype);
|
|
61
62
|
const itemBytes = components * bpe;
|
|
63
|
+
const actualStride = stride ?? itemBytes;
|
|
64
|
+
const actualOffset = offsetInBytes ?? 0;
|
|
62
65
|
const normalized = dtype === 'u8';
|
|
63
66
|
// 非交错:整段直接铺开
|
|
64
|
-
if (
|
|
67
|
+
if (actualStride === itemBytes && actualOffset === 0) {
|
|
65
68
|
const view = typedArray(dtype, data.buffer.slice(data.byteOffset, data.byteOffset + data.byteLength));
|
|
66
69
|
return new THREE.BufferAttribute(view, components, normalized);
|
|
67
70
|
}
|
|
68
71
|
// 交错:逐元素抽取
|
|
69
|
-
const count = Math.floor(data.byteLength /
|
|
72
|
+
const count = Math.floor(data.byteLength / actualStride);
|
|
70
73
|
const out = typedArrayOf(dtype, count * components);
|
|
71
74
|
const dv = new DataView(data.buffer, data.byteOffset, data.byteLength);
|
|
72
75
|
for (let i = 0; i < count; i++) {
|
|
73
|
-
const base = i *
|
|
76
|
+
const base = i * actualStride + actualOffset;
|
|
74
77
|
for (let c = 0; c < components; c++) {
|
|
75
78
|
const o = base + c * bpe;
|
|
76
79
|
out[i * components + c] =
|
|
@@ -137,6 +140,15 @@ function materialUnits(m) {
|
|
|
137
140
|
const raw = m?.textureStates ?? m?.textureunitstates ?? [];
|
|
138
141
|
return raw.map((u) => u?.textureunitstate ?? u).filter((u) => !!u);
|
|
139
142
|
}
|
|
143
|
+
/** 判断 4x4 矩阵是否为标准单位矩阵 */
|
|
144
|
+
function isIdentityMatrix4(m) {
|
|
145
|
+
if (m.length !== 16)
|
|
146
|
+
return false;
|
|
147
|
+
return (m[0] === 1 && m[1] === 0 && m[2] === 0 && m[3] === 0 &&
|
|
148
|
+
m[4] === 0 && m[5] === 1 && m[6] === 0 && m[7] === 0 &&
|
|
149
|
+
m[8] === 0 && m[9] === 0 && m[10] === 1 && m[11] === 0 &&
|
|
150
|
+
m[12] === 0 && m[13] === 0 && m[14] === 0 && m[15] === 1);
|
|
151
|
+
}
|
|
140
152
|
/** cullMode:1.x 用 none/clockwise/backward,3.x 用 CULL_NONE / CULL_BACK / CULL_FRONT */
|
|
141
153
|
function resolveSide(m) {
|
|
142
154
|
const cull = String(m?.cullMode ?? '').toUpperCase();
|
|
@@ -181,19 +193,50 @@ export async function buildTileObjects(tile, options = {}) {
|
|
|
181
193
|
stats.skipped.push(`texture ${code} → ${decoded}`);
|
|
182
194
|
}
|
|
183
195
|
}
|
|
184
|
-
// 2)
|
|
196
|
+
// 2) 材质描述表与材质池缓存
|
|
185
197
|
const materialList = resolveMaterialList(tile.materials);
|
|
198
|
+
const materialCache = new Map();
|
|
186
199
|
const makeMaterial = (code) => {
|
|
200
|
+
const cacheKey = code ?? '__default__';
|
|
201
|
+
const cached = materialCache.get(cacheKey);
|
|
202
|
+
if (cached)
|
|
203
|
+
return cached;
|
|
187
204
|
const entry = materialList.find((e) => materialName(unwrapMaterial(e)) === code);
|
|
188
205
|
const m = unwrapMaterial(entry);
|
|
189
206
|
const units = materialUnits(m);
|
|
190
|
-
const
|
|
207
|
+
const unit0 = units[0];
|
|
208
|
+
let map = unit0 ? (textureByCode.get(materialName(unit0) ?? unit0.id ?? '') ?? null) : null;
|
|
209
|
+
// 检查并应用 texmodmatrix 纹理变换矩阵
|
|
210
|
+
const texMod = unit0?.texmodmatrix ?? unit0?.matrix;
|
|
211
|
+
if (map && Array.isArray(texMod) && texMod.length === 16 && !isIdentityMatrix4(texMod)) {
|
|
212
|
+
map = map.clone();
|
|
213
|
+
map.matrixAutoUpdate = false;
|
|
214
|
+
// S3M texmodmatrix 为 4x4 列主序矩阵 [m0..m15],对应 2D 仿射变换:
|
|
215
|
+
// u' = m[0]*u + m[4]*v + m[12]
|
|
216
|
+
// v' = m[1]*u + m[5]*v + m[13]
|
|
217
|
+
// Three.js Matrix3.set 按行主序接收参数
|
|
218
|
+
map.matrix.set(texMod[0], texMod[4], texMod[12], texMod[1], texMod[5], texMod[13], 0, 0, 1);
|
|
219
|
+
}
|
|
220
|
+
// 纹理寻址模式(addressmode)
|
|
221
|
+
if (map && unit0?.addressmode) {
|
|
222
|
+
const u = unit0.addressmode.u;
|
|
223
|
+
const v = unit0.addressmode.v;
|
|
224
|
+
if (u !== undefined || v !== undefined) {
|
|
225
|
+
if (map.matrixAutoUpdate) {
|
|
226
|
+
map = map.clone();
|
|
227
|
+
}
|
|
228
|
+
if (u !== undefined)
|
|
229
|
+
map.wrapS = u === 0 ? THREE.RepeatWrapping : THREE.ClampToEdgeWrapping;
|
|
230
|
+
if (v !== undefined)
|
|
231
|
+
map.wrapT = v === 0 ? THREE.RepeatWrapping : THREE.ClampToEdgeWrapping;
|
|
232
|
+
}
|
|
233
|
+
}
|
|
191
234
|
const diffuse = m?.diffuse ?? { r: 1, g: 1, b: 1, a: 1 };
|
|
192
235
|
const alphaMode = m?.alphaMode;
|
|
193
236
|
const transparent = alphaMode === 'AM_BLEND' || (diffuse.a ?? 1) < 0.999 || m?.transparentsorting === true;
|
|
194
237
|
// S3M 的 shininess 是旧式 0~128 高光指数,粗略映射到粗糙度
|
|
195
238
|
const roughness = typeof m?.shininess === 'number' && m.shininess > 0 ? Math.max(0.15, 1 - m.shininess / 128) : 0.95;
|
|
196
|
-
|
|
239
|
+
const mat = createStyledMaterial({
|
|
197
240
|
uniforms,
|
|
198
241
|
map,
|
|
199
242
|
color: new THREE.Color(diffuse.r ?? 1, diffuse.g ?? 1, diffuse.b ?? 1),
|
|
@@ -202,6 +245,8 @@ export async function buildTileObjects(tile, options = {}) {
|
|
|
202
245
|
opacity: diffuse.a ?? 1,
|
|
203
246
|
roughness,
|
|
204
247
|
});
|
|
248
|
+
materialCache.set(cacheKey, mat);
|
|
249
|
+
return mat;
|
|
205
250
|
};
|
|
206
251
|
// 3) 骨架 → 几何。顶点是「骨架局部坐标」,真正位置由引用它的 Geode 矩阵决定。
|
|
207
252
|
const geoCache = new Map();
|
|
@@ -238,15 +283,6 @@ export async function buildTileObjects(tile, options = {}) {
|
|
|
238
283
|
attributes.aBatchId = batchAttr
|
|
239
284
|
? toBufferAttribute(batchAttr)
|
|
240
285
|
: new THREE.BufferAttribute(new Float32Array(vertexCount).fill(-1), 1);
|
|
241
|
-
if (!attributes.normal) {
|
|
242
|
-
const tmp = new THREE.BufferGeometry();
|
|
243
|
-
tmp.setAttribute('position', attributes.position);
|
|
244
|
-
tmp.computeVertexNormals();
|
|
245
|
-
const normal = tmp.getAttribute('normal');
|
|
246
|
-
if (normal)
|
|
247
|
-
attributes.normal = normal;
|
|
248
|
-
tmp.dispose();
|
|
249
|
-
}
|
|
250
286
|
const instanced = vp.instanceIndex !== -1 && (vp.instanceMode === 16 || vp.instanceMode === 17);
|
|
251
287
|
// 注意:indexPackages 属于 Skeleton(geoPackage[name]),不在 vertexPackage 里
|
|
252
288
|
skeletonInfo.set(name, { indexPackages: geo.indexPackages ?? [], instanced });
|
|
@@ -260,12 +296,212 @@ export async function buildTileObjects(tile, options = {}) {
|
|
|
260
296
|
geometry.setIndex(idx);
|
|
261
297
|
else
|
|
262
298
|
geometry.setDrawRange(0, vertexCount);
|
|
299
|
+
// 如果数据本身没有法线且是三角网格,必须在绑定了 index 之后计算法线
|
|
300
|
+
// 绝不能在未索引的 attributes.position 上算,否则非连续顶点会导致法线朝向错乱甚至越界 NaN 导致死黑面
|
|
301
|
+
if (!isLinePrimitive(pack.primitiveType) && !geometry.getAttribute('normal')) {
|
|
302
|
+
geometry.computeVertexNormals();
|
|
303
|
+
}
|
|
263
304
|
geometry.computeBoundingBox();
|
|
264
305
|
geometry.computeBoundingSphere();
|
|
265
306
|
geoCache.set(`${name}|${pi}`, { geometry, pack });
|
|
266
307
|
});
|
|
267
308
|
}
|
|
268
309
|
const IDENTITY = new THREE.Matrix4();
|
|
310
|
+
const batchGroups = new Map();
|
|
311
|
+
const mergeBatchGeometries = (candidates, material, tileRef) => {
|
|
312
|
+
let totalVertices = 0;
|
|
313
|
+
let totalIndices = 0;
|
|
314
|
+
let hasNormal = false;
|
|
315
|
+
let hasUv = false;
|
|
316
|
+
let hasUv1 = false;
|
|
317
|
+
let hasAColor = false;
|
|
318
|
+
let hasABatchId = false;
|
|
319
|
+
for (const c of candidates) {
|
|
320
|
+
const g = c.cached.geometry;
|
|
321
|
+
const vCount = g.attributes.position?.count ?? 0;
|
|
322
|
+
totalVertices += vCount;
|
|
323
|
+
totalIndices += g.index ? g.index.count : vCount;
|
|
324
|
+
if (g.attributes.normal)
|
|
325
|
+
hasNormal = true;
|
|
326
|
+
if (g.attributes.uv)
|
|
327
|
+
hasUv = true;
|
|
328
|
+
if (g.attributes.uv1)
|
|
329
|
+
hasUv1 = true;
|
|
330
|
+
if (g.attributes.aColor)
|
|
331
|
+
hasAColor = true;
|
|
332
|
+
if (g.attributes.aBatchId)
|
|
333
|
+
hasABatchId = true;
|
|
334
|
+
}
|
|
335
|
+
const mergedPos = new Float32Array(totalVertices * 3);
|
|
336
|
+
const mergedNorm = hasNormal ? new Float32Array(totalVertices * 3) : null;
|
|
337
|
+
const mergedUv = hasUv ? new Float32Array(totalVertices * 2) : null;
|
|
338
|
+
const mergedUv1 = hasUv1 ? new Float32Array(totalVertices * 2) : null;
|
|
339
|
+
const mergedColor = hasAColor ? new Float32Array(totalVertices * 3) : null;
|
|
340
|
+
const mergedBatchId = hasABatchId ? new Float32Array(totalVertices) : null;
|
|
341
|
+
const IndexArrayType = totalVertices > 65535 ? Uint32Array : Uint16Array;
|
|
342
|
+
const mergedIndices = new IndexArrayType(totalIndices);
|
|
343
|
+
let vertexOffset = 0;
|
|
344
|
+
let indexOffset = 0;
|
|
345
|
+
const tmpVec = new THREE.Vector3();
|
|
346
|
+
const normalMatrix = new THREE.Matrix3();
|
|
347
|
+
const geoByBatchId = new Map();
|
|
348
|
+
for (const c of candidates) {
|
|
349
|
+
const g = c.cached.geometry;
|
|
350
|
+
const vCount = g.attributes.position.count;
|
|
351
|
+
const m = c.matrix;
|
|
352
|
+
const hasTransform = m && !m.equals(IDENTITY);
|
|
353
|
+
if (hasTransform && hasNormal) {
|
|
354
|
+
normalMatrix.getNormalMatrix(m);
|
|
355
|
+
}
|
|
356
|
+
if (c.geo.pickInfo) {
|
|
357
|
+
for (const entry of Object.values(c.geo.pickInfo)) {
|
|
358
|
+
if (typeof entry.batchId === 'number' && entry.batchId >= 0) {
|
|
359
|
+
geoByBatchId.set(entry.batchId, c.geo);
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
// 1. Position
|
|
364
|
+
const posArr = g.attributes.position.array;
|
|
365
|
+
for (let i = 0; i < vCount; i++) {
|
|
366
|
+
const srcIdx = i * 3;
|
|
367
|
+
const dstIdx = (vertexOffset + i) * 3;
|
|
368
|
+
if (hasTransform) {
|
|
369
|
+
tmpVec.set(posArr[srcIdx], posArr[srcIdx + 1], posArr[srcIdx + 2]).applyMatrix4(m);
|
|
370
|
+
mergedPos[dstIdx] = tmpVec.x;
|
|
371
|
+
mergedPos[dstIdx + 1] = tmpVec.y;
|
|
372
|
+
mergedPos[dstIdx + 2] = tmpVec.z;
|
|
373
|
+
}
|
|
374
|
+
else {
|
|
375
|
+
mergedPos[dstIdx] = posArr[srcIdx];
|
|
376
|
+
mergedPos[dstIdx + 1] = posArr[srcIdx + 1];
|
|
377
|
+
mergedPos[dstIdx + 2] = posArr[srcIdx + 2];
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
// 2. Normal
|
|
381
|
+
if (mergedNorm) {
|
|
382
|
+
const normAttr = g.attributes.normal;
|
|
383
|
+
if (normAttr) {
|
|
384
|
+
const normArr = normAttr.array;
|
|
385
|
+
for (let i = 0; i < vCount; i++) {
|
|
386
|
+
const srcIdx = i * 3;
|
|
387
|
+
const dstIdx = (vertexOffset + i) * 3;
|
|
388
|
+
if (hasTransform) {
|
|
389
|
+
tmpVec
|
|
390
|
+
.set(normArr[srcIdx], normArr[srcIdx + 1], normArr[srcIdx + 2])
|
|
391
|
+
.applyMatrix3(normalMatrix)
|
|
392
|
+
.normalize();
|
|
393
|
+
mergedNorm[dstIdx] = tmpVec.x;
|
|
394
|
+
mergedNorm[dstIdx + 1] = tmpVec.y;
|
|
395
|
+
mergedNorm[dstIdx + 2] = tmpVec.z;
|
|
396
|
+
}
|
|
397
|
+
else {
|
|
398
|
+
mergedNorm[dstIdx] = normArr[srcIdx];
|
|
399
|
+
mergedNorm[dstIdx + 1] = normArr[srcIdx + 1];
|
|
400
|
+
mergedNorm[dstIdx + 2] = normArr[srcIdx + 2];
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
// 3. UV
|
|
406
|
+
if (mergedUv) {
|
|
407
|
+
const uvAttr = g.attributes.uv;
|
|
408
|
+
if (uvAttr) {
|
|
409
|
+
const uvArr = uvAttr.array;
|
|
410
|
+
for (let i = 0; i < vCount; i++) {
|
|
411
|
+
mergedUv[(vertexOffset + i) * 2] = uvArr[i * 2];
|
|
412
|
+
mergedUv[(vertexOffset + i) * 2 + 1] = uvArr[i * 2 + 1];
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
// 4. UV1
|
|
417
|
+
if (mergedUv1) {
|
|
418
|
+
const uv1Attr = g.attributes.uv1;
|
|
419
|
+
if (uv1Attr) {
|
|
420
|
+
const uvArr = uv1Attr.array;
|
|
421
|
+
for (let i = 0; i < vCount; i++) {
|
|
422
|
+
mergedUv1[(vertexOffset + i) * 2] = uvArr[i * 2];
|
|
423
|
+
mergedUv1[(vertexOffset + i) * 2 + 1] = uvArr[i * 2 + 1];
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
// 5. aColor
|
|
428
|
+
if (mergedColor) {
|
|
429
|
+
const colAttr = g.attributes.aColor;
|
|
430
|
+
if (colAttr) {
|
|
431
|
+
const colArr = colAttr.array;
|
|
432
|
+
for (let i = 0; i < vCount; i++) {
|
|
433
|
+
mergedColor[(vertexOffset + i) * 3] = colArr[i * 3];
|
|
434
|
+
mergedColor[(vertexOffset + i) * 3 + 1] = colArr[i * 3 + 1];
|
|
435
|
+
mergedColor[(vertexOffset + i) * 3 + 2] = colArr[i * 3 + 2];
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
else {
|
|
439
|
+
for (let i = 0; i < vCount; i++) {
|
|
440
|
+
mergedColor[(vertexOffset + i) * 3] = 1;
|
|
441
|
+
mergedColor[(vertexOffset + i) * 3 + 1] = 1;
|
|
442
|
+
mergedColor[(vertexOffset + i) * 3 + 2] = 1;
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
// 6. aBatchId
|
|
447
|
+
if (mergedBatchId) {
|
|
448
|
+
const bAttr = g.attributes.aBatchId;
|
|
449
|
+
if (bAttr) {
|
|
450
|
+
const bArr = bAttr.array;
|
|
451
|
+
for (let i = 0; i < vCount; i++) {
|
|
452
|
+
mergedBatchId[vertexOffset + i] = bArr[i];
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
else {
|
|
456
|
+
for (let i = 0; i < vCount; i++) {
|
|
457
|
+
mergedBatchId[vertexOffset + i] = -1;
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
// 7. Indices
|
|
462
|
+
if (g.index) {
|
|
463
|
+
const idxArr = g.index.array;
|
|
464
|
+
const iCount = g.index.count;
|
|
465
|
+
for (let k = 0; k < iCount; k++) {
|
|
466
|
+
mergedIndices[indexOffset + k] = idxArr[k] + vertexOffset;
|
|
467
|
+
}
|
|
468
|
+
indexOffset += iCount;
|
|
469
|
+
}
|
|
470
|
+
else {
|
|
471
|
+
for (let k = 0; k < vCount; k++) {
|
|
472
|
+
mergedIndices[indexOffset + k] = k + vertexOffset;
|
|
473
|
+
}
|
|
474
|
+
indexOffset += vCount;
|
|
475
|
+
}
|
|
476
|
+
vertexOffset += vCount;
|
|
477
|
+
}
|
|
478
|
+
const mergedGeo = new THREE.BufferGeometry();
|
|
479
|
+
mergedGeo.setAttribute('position', new THREE.BufferAttribute(mergedPos, 3));
|
|
480
|
+
if (mergedNorm)
|
|
481
|
+
mergedGeo.setAttribute('normal', new THREE.BufferAttribute(mergedNorm, 3));
|
|
482
|
+
if (mergedUv)
|
|
483
|
+
mergedGeo.setAttribute('uv', new THREE.BufferAttribute(mergedUv, 2));
|
|
484
|
+
if (mergedUv1)
|
|
485
|
+
mergedGeo.setAttribute('uv1', new THREE.BufferAttribute(mergedUv1, 2));
|
|
486
|
+
if (mergedColor)
|
|
487
|
+
mergedGeo.setAttribute('aColor', new THREE.BufferAttribute(mergedColor, 3));
|
|
488
|
+
if (mergedBatchId)
|
|
489
|
+
mergedGeo.setAttribute('aBatchId', new THREE.BufferAttribute(mergedBatchId, 1));
|
|
490
|
+
mergedGeo.setIndex(new THREE.BufferAttribute(mergedIndices, 1));
|
|
491
|
+
mergedGeo.computeBoundingBox();
|
|
492
|
+
mergedGeo.computeBoundingSphere();
|
|
493
|
+
const mesh = new THREE.Mesh(mergedGeo, material);
|
|
494
|
+
mesh.userData.skeletonName = candidates[0].name;
|
|
495
|
+
mesh.userData.geoRef = candidates[0].geo;
|
|
496
|
+
mesh.userData.tileRef = tileRef;
|
|
497
|
+
mesh.userData.primitiveType = 4;
|
|
498
|
+
mesh.userData.isBatched = true;
|
|
499
|
+
mesh.userData.batchedCount = candidates.length;
|
|
500
|
+
if (geoByBatchId.size > 0) {
|
|
501
|
+
mesh.userData.geoByBatchId = geoByBatchId;
|
|
502
|
+
}
|
|
503
|
+
return mesh;
|
|
504
|
+
};
|
|
269
505
|
const placeObject = (cached, name, geo, matrix) => {
|
|
270
506
|
const { geometry, pack } = cached;
|
|
271
507
|
const material = makeMaterial(pack.passNames?.[0]);
|
|
@@ -350,12 +586,32 @@ export async function buildTileObjects(tile, options = {}) {
|
|
|
350
586
|
const geo = tile.geoPackage[name];
|
|
351
587
|
if (!geo)
|
|
352
588
|
continue;
|
|
589
|
+
const vp = geo.vertexPackage;
|
|
353
590
|
for (let pi = 0; pi < info.indexPackages.length; pi++) {
|
|
354
591
|
const cached = geoCache.get(`${name}|${pi}`);
|
|
355
|
-
if (cached)
|
|
592
|
+
if (!cached)
|
|
593
|
+
continue;
|
|
594
|
+
// 棱线包或实例化网格:保持单独摆放
|
|
595
|
+
if (isLinePrimitive(cached.pack.primitiveType) ||
|
|
596
|
+
(info.instanced && vp.instanceBuffer && vp.instanceCount > 0)) {
|
|
356
597
|
placeObject(cached, name, geo, matrix);
|
|
357
598
|
placed++;
|
|
599
|
+
continue;
|
|
358
600
|
}
|
|
601
|
+
// 普通三角面网格:若开启合批,按材质进行分组收集
|
|
602
|
+
if (options.batching !== false && cached.pack.primitiveType === 4) {
|
|
603
|
+
const matKey = cached.pack.passNames?.[0] ?? '__default__';
|
|
604
|
+
let list = batchGroups.get(matKey);
|
|
605
|
+
if (!list) {
|
|
606
|
+
list = [];
|
|
607
|
+
batchGroups.set(matKey, list);
|
|
608
|
+
}
|
|
609
|
+
list.push({ cached, name, geo, matrix });
|
|
610
|
+
placed++;
|
|
611
|
+
continue;
|
|
612
|
+
}
|
|
613
|
+
placeObject(cached, name, geo, matrix);
|
|
614
|
+
placed++;
|
|
359
615
|
}
|
|
360
616
|
}
|
|
361
617
|
}
|
|
@@ -366,10 +622,46 @@ export async function buildTileObjects(tile, options = {}) {
|
|
|
366
622
|
const geo = tile.geoPackage[name];
|
|
367
623
|
if (!geo)
|
|
368
624
|
continue;
|
|
625
|
+
const vp = geo.vertexPackage;
|
|
369
626
|
for (let pi = 0; pi < info.indexPackages.length; pi++) {
|
|
370
627
|
const cached = geoCache.get(`${name}|${pi}`);
|
|
371
|
-
if (cached)
|
|
628
|
+
if (!cached)
|
|
629
|
+
continue;
|
|
630
|
+
if (isLinePrimitive(cached.pack.primitiveType) ||
|
|
631
|
+
(info.instanced && vp.instanceBuffer && vp.instanceCount > 0)) {
|
|
372
632
|
placeObject(cached, name, geo, null);
|
|
633
|
+
continue;
|
|
634
|
+
}
|
|
635
|
+
if (options.batching !== false && cached.pack.primitiveType === 4) {
|
|
636
|
+
const matKey = cached.pack.passNames?.[0] ?? '__default__';
|
|
637
|
+
let list = batchGroups.get(matKey);
|
|
638
|
+
if (!list) {
|
|
639
|
+
list = [];
|
|
640
|
+
batchGroups.set(matKey, list);
|
|
641
|
+
}
|
|
642
|
+
list.push({ cached, name, geo, matrix: null });
|
|
643
|
+
continue;
|
|
644
|
+
}
|
|
645
|
+
placeObject(cached, name, geo, null);
|
|
646
|
+
}
|
|
647
|
+
}
|
|
648
|
+
}
|
|
649
|
+
// 执行同材质几何合批
|
|
650
|
+
if (batchGroups.size > 0) {
|
|
651
|
+
for (const [matKey, list] of batchGroups) {
|
|
652
|
+
stats.originalMeshes = (stats.originalMeshes ?? 0) + list.length;
|
|
653
|
+
if (list.length === 1) {
|
|
654
|
+
placeObject(list[0].cached, list[0].name, list[0].geo, list[0].matrix);
|
|
655
|
+
}
|
|
656
|
+
else {
|
|
657
|
+
const material = makeMaterial(matKey === '__default__' ? undefined : matKey);
|
|
658
|
+
const batchedMesh = mergeBatchGeometries(list, material, tile);
|
|
659
|
+
group.add(batchedMesh);
|
|
660
|
+
objects.push(batchedMesh);
|
|
661
|
+
stats.meshes++;
|
|
662
|
+
for (const item of list) {
|
|
663
|
+
stats.triangles += (item.cached.pack.indexCount || 0) / 3;
|
|
664
|
+
}
|
|
373
665
|
}
|
|
374
666
|
}
|
|
375
667
|
}
|