# 3DTile (3D 瓦片)

- **Summary**: Five 用于加载和渲染大规模三维场景的核心模块，支持动态 LOD 调度与流式加载。
- **Schema**: 对应 `ParameterTilesetValue` 接口，通过 Parameter 配置 LOD、显存与并发控制。
- **Concepts**: LOD (细节层级), SSE (屏幕空间误差), Cache Management (显存管理), ViewLayer (视图层)。
- **Configuration**: 包含画质精度、显存配额、几何误差、并发请求等详细参数。
- **Examples**: 画质平衡与多图层优化。

## Schema

> **Definition**: [ParameterTilesetValue](../../five/model/parameter.d.ts)

以下是 `ParameterTilesetValue` 的 TypeScript 定义摘要：

```typescript
export interface ParameterTilesetValue {
  /** 屏幕空间误差阈值 (像素) */
  maxScreenSpaceError: number;
  /** 最大显存占用 (MB) */
  maxMemoryUsage: number;
  /** 最小几何误差 (精度上限锁) */
  minGeometricError: number;
  // ... 更多字段见下方配置表
}
```

## Concepts

### 1. LOD & Screen Space Error (SSE)

LOD (Level of Detail) 是 3DTile 的核心机制。引擎不会一次性加载整个从宏观到微观的所有模型数据，而是根据相机位置动态计算每个瓦片的 **屏幕空间误差 (SSE)**。

*   **Geometric Error (几何误差)**: 3D Tiles 数据源中定义的指标（单位：米），表示当前瓦片与真实物体之间的最大形状差异。
    *   **根节点**: 误差巨大（如 100米），仅有模糊轮廓。
    *   **叶子节点**: 误差极小（如 0.01米），细节丰富。
*   **SSE 计算逻辑**: `SSE = (GeometricError / DistanceToCamera) * ScreenHeight`。
*   **判定标准**: 如果 `SSE > maxScreenSpaceError`，说明当前瓦片在屏幕上看起来太粗糙（误差像素太大），需要分裂并加载下一级子瓦片；反之则停止细分。
*   **调整影响**: 调低 `maxScreenSpaceError` 会迫使引擎加载更深层级的瓦片，从而获得更清晰的细节，但也会急剧增加渲染三角形数量和显存占用。

### 2. 显存管理 (Cache Management)

为了在浏览器有限的资源下渲染海量数据（如城市级倾斜摄影），3DTile 实现了基于 LRU (Least Recently Used) 的缓存淘汰机制和动态画质调整策略。

*   **LRU 淘汰**: 当 `maxMemoryUsage` 超限时，引擎会优先保留当前视锥体内的瓦片。视锥体外的、或者距离相机较远的瓦片会被优先释放。
*   **动态画质调整 (Dynamic Scaling)**: 如果开启了 `memoryAdjustedScreenSpaceError`，引擎会以 `maxMemoryUsage` 为目标，实时调整 SSE。
    *   **目标**: 尽量跑满 `maxMemoryUsage` 设定的显存额度，不浪费资源。
    *   **范围**: 实际 SSE 会在 `1.0` (极高画质) 到 `maxScreenSpaceError` (设定底线) 之间波动。
    *   **场景**: 适合显存充足但希望自动平衡画质的场景。

### 3. ViewLayer 与 3DTile

目前所有的 `ViewLayer` 在底层都是一个 `Tile3D` 实例。它们各自拥有独立的：
*   **配置**: `maxScreenSpaceError`, `maxMemoryUsage` 等参数互不干扰。
*   **缓存**: 显存配额各自独立计算。

> **注意**: 即使是通过 `file_url` 加载的单体模型（如 `.obj`, `.at3d`），在 Five 内部也会被封装为 `Tile3D` 实例进行统一管理。

## Configuration

以下表格列出了控制 3DTile 加载与性能调度的所有可用参数。

### Core Quality & Performance (核心画质与性能)

| Parameter | Type | Default | Description |
| :--- | :--- | :--- | :--- |
| `maxScreenSpaceError` | `number` | `16` | **核心参数**。屏幕空间误差阈值 (像素)。<br>值越小画质越高，性能开销越大。建议范围 8-32。 |
| `maxMemoryUsage` | `number` | `512` | 最大显存占用 (MB)。超限后自动触发 LRU 淘汰机制。 |
| `memoryAdjustedScreenSpaceError` | `boolean` | `false` | 是否开启基于内存的动态 SSE 调整。<br>开启后引擎会自动调整 SSE 以尽量占满显存配额。 |
| `cameraCulling` | `boolean` | `true` | 是否开启视锥体剔除 (不加载视野外的瓦片)。**建议始终开启**。 |

### Geometric Error Control (几何误差控制)

| Parameter | Type | Default | Description |
| :--- | :--- | :--- | :--- |
| `minGeometricError` | `number` | `0` | 最小几何误差 (精度上限锁)。<br>当瓦片误差小于此值时停止细分。可用于限制过高精度的加载。 |
| `maxGeometricError` | `number` | `10000` | 最大几何误差 (最低精度保证)。<br>强制细分直到误差小于此值。可用于避免模型过于模糊。 |

### Network & Loading (网络与加载)

| Parameter | Type | Default | Description |
| :--- | :--- | :--- | :--- |
| `maxRequests` | `number` | `4` | 最大并发请求数。建议保持默认，避免网络拥堵。 |
| `requestOrder` | `string` | `'SCREEN_SPACE_ERROR'` | 请求优先级策略。<br>`'SCREEN_SPACE_ERROR'`: 优先加载 SSE 大的瓦片；<br>`'SCREEN_LEVEL_VERTICAL'`: 优先加载垂直层级高的。 |
| `loadSiblings` | `boolean` | `true` | 是否预加载兄弟节点。 |
| `skipLevelOfDetail` | `boolean` | `false` | 是否允许跳级加载 (跳过中间层级直接加载高精瓦片)。 |

### Legacy LOD Control (不推荐)

| Parameter | Type | Default | Description |
| :--- | :--- | :--- | :--- |
| `minLevelOfDetail` | `number` | `0` | 最小 LOD 层级 (Tree Depth)。建议使用 `maxGeometricError` 替代。 |
| `maxLevelOfDetail` | `number` | `20` | 最大 LOD 层级 (Tree Depth)。建议使用 `minGeometricError` 替代。 |

## Examples

### 1. Adjusting Quality & Memory (调整画质与内存平衡)

在移动端或性能受限设备上，建议适当降低画质以保证流畅度。

```typescript
const parameter = five.modelScene.parameter;

// 1. 性能优先模式 (适用于低端设备)
// 增大 SSE 阈值，降低画质
parameter.set('maxScreenSpaceError', 16);
// 限制显存，防止 Crash
parameter.set('maxMemoryUsage', 256);

// 2. 画质优先模式 (适用于桌面端/截图)
// 减小 SSE 阈值，提升细节
parameter.set('maxScreenSpaceError', 4);
// 允许更多显存占用
parameter.set('maxMemoryUsage', 1024);

// 3. 重置为默认
parameter.reset('maxScreenSpaceError', 'maxMemoryUsage');
```

### 2. Multi-ViewLayer Optimization (多 ViewLayer 优化)

在对比查看或多楼层场景中，通常存在多个 `ViewLayer`。为了避免资源竞争，建议对非焦点的 ViewLayer 进行降级处理。

```typescript
// 假设 viewLayerA 是当前主要查看的模型，viewLayerB 是背景参考

// 聚焦 ViewLayerA: 正常画质
viewLayerA.parameter.reset('maxScreenSpaceError');

// 降级 ViewLayerB: 仅显示轮廓，节省资源
viewLayerB.parameter.set('maxScreenSpaceError', 48); // 极低画质
viewLayerB.parameter.set('maxMemoryUsage', 128);     // 极低显存配额
```

## Debugging

在开发过程中，可以通过访问 `ViewLayer` 内部的 `tileset` 对象来实时监控渲染状态。

```typescript
// 假设已获取 viewLayer 实例
const tileset = viewLayer.tileset;

// 1. 查看当前加载的瓦片数量
console.log(tileset.loadedTiles.size);

// 2. 查看当前实际生效的 SSE (如果开启了动态调整，此值会波动)
console.log(tileset.currentMaxScreenSpaceError);

// 3. 查看显存占用 (近似值，单位字节)
// 注意: 这是内部私有属性，仅供调试参考
console.log((tileset as any).cacheMemoryUsageInBytes / 1024 / 1024 + ' MB');
```

## Common Pitfalls

1.  **误解 GeometricError 作用域**: `minGeometricError` 和 `maxGeometricError` 是**全局硬约束**，不随相机距离变化。
    *   错误设置（例如将 `maxGeometricError` 设得极小）会强制全场景所有瓦片（哪怕是远处的背景）都加载到极高精度。
    *   这会导致三角形数量和显存占用**指数级爆炸**，瞬间卡死浏览器。
2.  **过度降低 `maxScreenSpaceError`**: 设置过小（如 < 4）可能导致每帧需要加载和渲染的三角形数量指数级上升，瞬间撑爆显存或导致掉帧。
3.  **忽略 `cameraCulling`**: 默认应该开启。如果手动关闭视锥体剔除，引擎将尝试加载全场景数据，极易导致崩溃。
4.  **频繁切换配置**: `maxMemoryUsage` 等参数的修改会触发缓存整理，高频修改可能导致卡顿。

## Related

*   [Parameter](./parameter.md): 了解参数的继承关系及材质、点云相关配置。
*   [Model](./model.md): 了解 Model 和 ViewLayer 的关系。
*   [Work](./work.md): 了解 Work 数据结构。

---

```yaml
tags: [大场景, 瓦片, 显存, 画质, 性能优化, 流式加载, 3dtile, viewLayer, performance, lod, optimization, tile-loading, memory, sse, screen-space-error]
```
