Add optional GLB compression stage
This commit is contained in:
@@ -18,6 +18,105 @@
|
||||
全部是 CommonJS(`package.json` 的 `"type": "commonjs"`),无构建步骤、无 TypeScript、
|
||||
零运行时依赖(唯一依赖 `osm2streets-js-node` 只被 `build-osm2streets-qgis.js` 用)。
|
||||
|
||||
## 可选 GLB 压缩阶段
|
||||
|
||||
### 1. Scope / Trigger
|
||||
|
||||
`compress` 是显式请求的替代产物阶段,不属于 `all`,也不覆盖默认 `<area-id>.glb`。
|
||||
它用于在已有 Cesium GLB 上生成并列压缩 GLB、metadata 和预览页。当前主路径是
|
||||
texture resize + WebP transcode。
|
||||
|
||||
`scripts/compress-glb.js` 是该阶段调用的低层脚本,也可单独运行做实验。
|
||||
|
||||
### 2. Signatures
|
||||
|
||||
阶段入口:
|
||||
|
||||
```bash
|
||||
npm run build:area -- --config config/areas/<area>.json --stages compress
|
||||
npm run build:area -- --config config/areas/<area>.json --stages cesium,compress
|
||||
```
|
||||
|
||||
低层脚本入口:
|
||||
|
||||
```bash
|
||||
npm run compress:glb -- --input in.glb --output out.glb [options]
|
||||
```
|
||||
|
||||
可选参数:
|
||||
|
||||
| 参数 | 默认 | 语义 |
|
||||
|---|---:|---|
|
||||
| `--texture-size` | `1024` | 最大纹理宽高,范围 `64..4096` |
|
||||
| `--quality` | `82` | WebP 质量,范围 `1..100` |
|
||||
| `--effort` | `80` | WebP 编码 effort,范围 `0..100` |
|
||||
| `--meshopt` | off | 追加 `EXT_meshopt_compression` |
|
||||
| `--metadata source.json` | none | 复制伴生 metadata 并指向压缩 GLB |
|
||||
| `--metadata-output out.json` | `<output>.json` | 覆盖 metadata 输出路径 |
|
||||
| `--preview source.html` | none | 复制 Cesium preview 并指向压缩 metadata |
|
||||
| `--preview-output out.html` | `<output>-cesium-preview.html` | 覆盖 preview 输出路径 |
|
||||
|
||||
### 3. Contracts
|
||||
|
||||
- 输入必须是现有 `.glb` 文件;`--output` 必须不同于 `--input`。
|
||||
- 输出是并列压缩 GLB;默认构建产物不被替换。
|
||||
- `compress` 阶段依赖默认 `glb`、`metadata` 和 `cesiumPreview` 已存在。
|
||||
- 默认链固定为 `gltf-transform resize -> gltf-transform webp`。
|
||||
- `compress` 阶段默认 `textureSize=768`;低层脚本单独运行时默认 `--texture-size 1024`。
|
||||
- `build-area.js` 默认写:
|
||||
- `<fileStem>-compressed-webp768.glb`
|
||||
- `<fileStem>-compressed-webp768.json`
|
||||
- `<fileStem>-compressed-webp768-cesium-preview.html`
|
||||
- 伴生 metadata 的 `asset` 和 `assets[0].url` 改为压缩 GLB 文件名。
|
||||
- preview HTML 只替换 `window.OSM_ASSET_PREVIEW_CONFIG` 的 `glbName` /
|
||||
`metadataName` 和 loading 文案,不改 preview runtime。
|
||||
- 成功时 stdout 打印 `GLB_COMPRESS_DONE <json>`,包含压缩前后大小、image /
|
||||
non-image bytes、结构计数、扩展、metadata / preview 输出路径。
|
||||
|
||||
### 4. Validation & Error Matrix
|
||||
|
||||
| 条件 | 结果 |
|
||||
|---|---|
|
||||
| 缺 `--input` / `--output` | 打印 usage 并退出非零 |
|
||||
| 输入文件不存在 | `Input GLB not found: <path>` |
|
||||
| `--output` 等于 `--input` | 抛错,避免覆盖源 GLB |
|
||||
| 数值参数超范围 | 抛错并指出合法范围 |
|
||||
| `gltf-transform` 退出非零 | 抛错并带上 status / signal |
|
||||
| `--preview` 没有 `--metadata` | 抛错,因为 preview 必须指向存在的 metadata |
|
||||
| preview HTML 找不到配置块 | 抛错,不做猜测替换 |
|
||||
| `--stages compress` 但默认 preview 不存在 | `Cesium preview not found: <path>` |
|
||||
|
||||
### 5. Good/Base/Bad Cases
|
||||
|
||||
- Good: `--stages cesium,compress` 先重导默认 GLB,再生成并列压缩产物。
|
||||
- Good: `--texture-size 768 --metadata --preview` 生成压缩 GLB、metadata、HTML,
|
||||
源 GLB 保持不变。
|
||||
- Base: 只传 `--input --output` 生成压缩 GLB,不生成伴生文件。
|
||||
- Bad: 使用 `--meshopt` 后没有做 Cesium 兼容性验证就当默认产物发布。
|
||||
|
||||
### 6. Tests Required
|
||||
|
||||
- `node --check scripts/compress-glb.js`
|
||||
- `node --check scripts/build-area.js`
|
||||
- 对目标区域跑一次 `npm run compress:glb -- ... --metadata --preview`
|
||||
- 对目标区域跑一次 `npm run build:area -- --stages compress`
|
||||
- `node scripts/glb-digest.js <compressed.glb>` 确认可解析结构和扩展
|
||||
- 浏览器/Cesium 预览压缩 HTML,确认 `EXT_texture_webp` 在目标环境可加载
|
||||
|
||||
### 7. Wrong vs Correct
|
||||
|
||||
Wrong:
|
||||
|
||||
```bash
|
||||
npm run compress:glb -- --input outputs/a/a.glb --output outputs/a/a.glb
|
||||
```
|
||||
|
||||
Correct:
|
||||
|
||||
```bash
|
||||
npm run compress:glb -- --input outputs/a/a.glb --output outputs/a/a-compressed-webp768.glb
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## CLI 参数解析
|
||||
@@ -94,7 +193,7 @@ gpkg: path.resolve(outputOverrides.gpkg || path.join(areaDir, `${fileStem}.gpkg`
|
||||
|
||||
---
|
||||
|
||||
## 五个阶段
|
||||
## 阶段
|
||||
|
||||
| 阶段 | 做什么 | 读 | 写 |
|
||||
|---|---|---|---|
|
||||
@@ -103,8 +202,9 @@ gpkg: path.resolve(outputOverrides.gpkg || path.join(areaDir, `${fileStem}.gpkg`
|
||||
| `blender` | OSM + GeoJSON → 场景 | `.osm`、`osm2streets_web_out/` | `.blend`、`.png` |
|
||||
| `cesium` | 场景 → GLB + 元数据 + 预览页 | `.blend` | `.glb`、`.json`、预览 HTML 及其静态资源 |
|
||||
| `preview` | 只补生成预览页 | `.glb`、`.json` | 预览 HTML 及其静态资源 |
|
||||
| `compress` | 生成并列压缩 Cesium 产物 | `.glb`、`.json`、默认预览 HTML | `-compressed-webp*.glb/json/html` |
|
||||
|
||||
调度是顶层的五个 `if`(`build-area.js:32-46`),顺序固定,**阶段之间不传内存状态,
|
||||
调度是顶层的阶段 `if`(`build-area.js` 开头),顺序固定,**阶段之间不传内存状态,
|
||||
只通过磁盘产物耦合**。这就是单跑某个阶段能work 的原因。
|
||||
|
||||
`cesium` 阶段结束时会直接调 `writeCesiumPreview(area)`(`build-area.js:285`),所以
|
||||
@@ -126,7 +226,8 @@ gpkg: path.resolve(outputOverrides.gpkg || path.join(areaDir, `${fileStem}.gpkg`
|
||||
all: ["intermediates", "blender", "cesium"],
|
||||
```
|
||||
|
||||
`preview` 同样不在 `all` 里——`cesium` 已经包含它。
|
||||
`preview` 同样不在 `all` 里——`cesium` 已经包含它。`compress` 也不在 `all` 里——
|
||||
它生成的是替代压缩产物,不是 baseline GLB。
|
||||
|
||||
### `intermediates` 与 `reimport` 互斥
|
||||
|
||||
@@ -136,9 +237,9 @@ all: ["intermediates", "blender", "cesium"],
|
||||
|
||||
这是**显式拒绝而不是警告**——两者同时开,无论谁先跑,另一个的工作都白做。
|
||||
|
||||
`normalizeAreaConfig` 里 `stages.reimport` 和 `stages.preview` 硬编码为 `false`
|
||||
(`build-area.js:117-118`),**不能从配置文件打开**,只能靠 `--stages` 显式请求。
|
||||
恢复动作和补丁动作都不该被一份配置文件变成默认行为。
|
||||
`normalizeAreaConfig` 里 `stages.reimport`、`stages.preview` 和 `stages.compress` 硬编码为 `false`,
|
||||
**不能从配置文件打开**,只能靠 `--stages` 显式请求。
|
||||
恢复动作、补丁动作和替代产物动作都不该被一份配置文件变成默认行为。
|
||||
|
||||
---
|
||||
|
||||
|
||||
Reference in New Issue
Block a user