# Model (模型)

- **Summary**: Model 是 Five 中三维场景的核心实体，负责管理三维模型数据的加载、渲染和交互。
- **Schema**: 继承自 THREE.Object3D，包含 ViewLayer 等子对象。
- **Concepts**: ViewLayer, Parameter, 3DTile, five.ready()。
- **Examples**: 模型操作与事件监听。

## Schema

### Model

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

Model 类继承自 `THREE.Object3D`，是三维场景中的顶级对象。

```typescript
// 简化版定义，完整定义参考 lib/five/model/model.ts
class Model extends THREE.Object3D {
  /** 唯一标识 */
  public fiveId: string;

  /** 对应的 Work 数据 */
  public work: Work;

  /** 模型参数配置 */
  public parameter: Parameter;

  /** 包含的视图层 (如 mesh, point_cloud, gaussian_splatting) */
  public viewLayers: ViewLayer[];

  /** 是否加载完成 (初次加载) */
  public loaded: boolean;

  /** 是否细化完成 (高清纹理/模型加载完毕) */
  public refined: boolean;

  /** 细化进度 [当前, 总数] */
  public refineProgress: [number, number];

  /** 外包围盒 */
  public boundingBox: THREE.Box3;

  /** 楼层数量 */
  public floorLength: number;
}
```

> **refineProgress 说明**:
> *   类型: `[number, number]`
> *   含义: `[已处理的瓦片/纹理数量, 总瓦片/纹理数量]`。
> *   用途: 用于计算模型加载/细化的百分比进度 (progress = current / total)。

## Concepts

### 1. `five.models` vs `five.model`

*   **`five.models`**: 这是一个数组，返回当前场景中所有已加载的 `Model` 实例列表。
*   **`five.model`**: 这是一个便捷属性，直接返回 `five.models[0]`。

通常情况下，如果你只加载了一个 Work，可以直接使用 `five.model` 来操作当前模型。

```typescript
// 下面两种方式是等价的
const model1 = five.models[0];
const model2 = five.model;
```

### 2. Model vs Work

*   **Work (数据)**: 它是静态的描述数据（JSON），包含了模型的下载地址（URL）、元数据（Metadata）、初始状态等。它是“菜谱”。
*   **Model (实体)**: 它是运行时的三维对象（Object3D），包含了实际的几何体（Geometry）、材质（Material）和渲染状态。它是“菜肴”。

关系：`five.load(work)` 过程就是根据 Work 数据创建 Model 实体的过程。

### 3. ViewLayer 分层思想

一个完整的 VR 模型通常由多个部分组成，Five 使用 **ViewLayer** 来管理这些分层。

常见的 ViewLayer 类型：
*   **`mesh` (网格层)**: 也就是可以看到的实体模型（墙面、地板等）。
*   **`point_cloud` (点云层)**: 激光点云数据。它并非低精度数据，同样支持高精度的近距离观察，并支持碰撞检测。
*   **`gaussian_splatting` (高斯泼溅层)**: 新一代三维重建渲染技术，用于展示极高真实感的场景细节。

**层级结构**:
Model 加载完成后，会自动根据 Work 数据生成对应的 ViewLayer，并挂载为 `Model` 的子对象。开发者可以通过 `model.viewLayers` 访问它们。

```text
Model (Object3D)
  ├── ViewLayer (mesh)   -> 负责网格模型渲染
  └── ViewLayer (point_cloud) -> 负责点云渲染
```

### 4. Parameter (简述)

`Model` 实例上挂载了一个 `parameter` 对象（`five.models[0].parameter`）。
它是专门用于控制 **模型渲染表现** 的配置器。

*   **作用**: 控制模型的透明度、显示的楼层、相机裁剪范围等。
*   **详情**: 详见 [Parameter](./parameter.md) (待创建)。

### 5. 3DTile (简述)

`ViewLayer` 的底层实现基于 **3DTile** 技术（类名为 `Tile3D`）。

*   **作用**: 实现大规模三维数据的流式加载（LOD）。它能根据相机距离动态加载不同精度的模型块，保证渲染性能。
*   **详情**: 详见 [3DTile](./3dtile.md) (待创建)。

### 6. five.ready()

`five.ready()` 是一个 Promise 方法，用于等待当前环境“准备就绪”。

*   **对于 Model 模式**: 它会等待 Model 几何体加载完成（`model.loaded` 为 true）。
*   **对于 Panorama 模式**: 它会等待全景图基本加载完成。

推荐在执行截图、复杂的模型操作前，先 `await five.ready()`。

### 7. 射线碰撞 (Raycaster)

Model 提供了高效的射线检测方法 `intersectRaycaster`，内置了 BVH 加速，性能优于 Three.js 原生方法。

*   **API**: `model.intersectRaycaster(raycaster: THREE.Raycaster): THREE.Intersection[]`
*   **用途**: 鼠标点击拾取、视线检测、碰撞检测。
*   **详情**: 详见 [Raycast](./raycast.md)。

## Events

Five 实例上会派发与 Model 相关的生命周期事件，开发者可以通过 `five.on()` 监听。

| 事件名 | 说明 | 回调参数 |
| :--- | :--- | :--- |
| **`model.load`** | 单个 Model 几何体加载完成时触发。此时模型可见，但纹理可能模糊。 | `{ model: Model, work: Work }` |
| **`models.refined`** | 所有 Model 的纹理细化完成（变清晰）时触发。 | `{ modelScene: ModelScene }` |
| **`model.changeShownFloor`** | Model 的楼层显隐状态发生变化时触发。 | `{ model: Model, work: Work }` |
| **`model.error`** | Model 加载出错时触发。 | `{ error: Error, model: Model, work: Work }` |

## Examples

### 获取并操作当前模型

```typescript
// 获取当前模型
const model = five.models[0];

if (model) {
  console.log("模型对应 Work 名称:", model.work.name);
  console.log("模型是否细化完成:", model.refined);

  // 监听模型细化事件
  five.on("model.refined", () => {
    console.log("模型高清资源加载完毕");
  });
}
```

### 遍历 ViewLayer

```typescript
const model = five.models[0];
// model.viewLayers 即为 ViewLayer 列表
model.viewLayers.forEach((layer) => {
  console.log(`图层名称: ${layer.name}, 类型: ${layer.type}`);

  if (layer.type === 'mesh') {
    // 对网格层做特殊处理
    layer.visible = true;
  }
});
```

## Common Pitfalls

1.  **直接修改 `model.children`**: 不要直接修改 `model.children` 数组。Model 的子对象是由 Five 内部管理的。如果需要隐藏某个图层，请设置 `layer.visible = false`。
2.  **混淆 `five.model` 和 `five.work`**: `five.model` 是 Three.js 对象 (Object3D)，用于渲染；`five.work` 是数据对象，用于描述。

## Related

*   [Work](./work.md): 了解 Work 数据结构。
*   [Parameter](./parameter.md): 了解模型参数配置。
*   [3DTile](./3dtile.md): 了解 3DTile 技术。
*   [Raycast](./raycast.md): 了解射线检测机制。

---

```yaml
tags: [模型, 三维模型, 点云, 高斯泼溅, 加载, 渲染, 图层, 楼层, 细化, model, viewlayer, object3d, mesh, refine]
```
