# Release Note 6.7.x
> 6.7.x 版本发布日志

```shell
npm install @realsee/five@6.7
```

## five.laod 的多 Work 的非阻塞性加载
> `five.load` 时，现在可选择追加或者替换。
> 并且在切换过程中，可以不再发生切换/锁定视角等妨碍用户持续操作的行为。
> 这方面的改动只要适用于多项目下，项目追加，分批次加载的情况。

### 使用 `FiveLoadOptions.mode` 在控制 替换 / 追加项目

```ts
// 替换项目
// mode: 'replace' 默认
five.load([parseWork(json1), parseWork(json2)], 'inherit', { mode: 'replace' });

// 追加项目
// mode: 'add'
five.load(parseWork(json2), 'inherit', { mode: 'add' });
```

注意事项：
- Work 的唯一标识依旧是 `workCode`。 同一场景下，不允许出现两个相同的 `workCode` 的 Work。如果出现会报错处理。
- 如果通过 `replace` 替换的 Work 的 `workCode` 和当前场景中有一样的（相当于替换一个一样的 Work），则会保留之前的 Work 的模型，直接挂在到新 Work 上，而不是重新加载。

### 重新定义 `state=inherit` 的行为

```ts
five.load(parseWork(json), 'inherit', { mode: 'add' });
```
当 `state=inherit` 时，在切换过程中，可以不再发生切换/锁定视角等妨碍用户持续操作的行为。

- 在模型态：保持当前视角状态
- 在全景态：如果当前 work 存在则不改变。不存在切换到一个可用的全景点。

## work 更加精简和灵活
> 针对大项目，对 work 的 json。做精简优化，减少网络传输时间。并且增加灵活性。

### panorama.pattern 模版
> 通过模版的模式匹配减少重复内容。
> panoram 中的 hash，index 等参数的重复度很高，对一样的内容可以通过这种方式减少文件长度。

Before:
```json
"panorama": {
  "count": 465,
  "list": [
    {
      "index": 0,
      "derived_id": 0,
      "derived_id_str": "auto3d-light-vEY8Zp4lPlkZ7R9K_1735117678",
      "up": "images/cube_2048/0/0fd265355dbb94cb22fb930e52dd3c19/0_u.jpg",
      "down": "images/cube_2048/0/0fd265355dbb94cb22fb930e52dd3c19/0_d.jpg",
      "left": "images/cube_2048/0/0fd265355dbb94cb22fb930e52dd3c19/0_l.jpg",
      "right": "images/cube_2048/0/0fd265355dbb94cb22fb930e52dd3c19/0_r.jpg",
      "front": "images/cube_2048/0/0fd265355dbb94cb22fb930e52dd3c19/0_f.jpg",
      "back": "images/cube_2048/0/0fd265355dbb94cb22fb930e52dd3c19/0_b.jpg",
      "size_list": [ 2048, 4096 ],
      "tiles": [ 1, 2, 3 ],

    },
    {
      "index": 1,
      "derived_id": 0,
      "derived_id_str": "auto3d-light-vEY8Zp4lPlkZ7R9K_1735117799",
      "up": "images/cube_2048/1/a6ca1991fc6bdb2dbd1a1003d9f62394/1_u.jpg",
      "down": "images/cube_2048/1/a6ca1991fc6bdb2dbd1a1003d9f62394/1_d.jpg",
      "left": "images/cube_2048/1/a6ca1991fc6bdb2dbd1a1003d9f62394/1_l.jpg",
      "right": "images/cube_2048/1/a6ca1991fc6bdb2dbd1a1003d9f62394/1_r.jpg",
      "front": "images/cube_2048/1/a6ca1991fc6bdb2dbd1a1003d9f62394/1_f.jpg",
      "back": "images/cube_2048/1/a6ca1991fc6bdb2dbd1a1003d9f62394/1_b.jpg",
      "size_list": [ 2048, 4096 ],
      "tiles": [ 1, 2, 3 ],
    },
    {
      "index": 2,
      "derived_id": 0,
      "derived_id_str": "auto3d-light-vEY8Zp4lPlkZ7R9K_1735117912",
      "up": "images/cube_2048/2/567f94406885bf06f5586d7972da2b5e/2_u.jpg",
      "down": "images/cube_2048/2/567f94406885bf06f5586d7972da2b5e/2_d.jpg",
      "left": "images/cube_2048/2/567f94406885bf06f5586d7972da2b5e/2_l.jpg",
      "right": "images/cube_2048/2/567f94406885bf06f5586d7972da2b5e/2_r.jpg",
      "front": "images/cube_2048/2/567f94406885bf06f5586d7972da2b5e/2_f.jpg",
      "back": "images/cube_2048/2/567f94406885bf06f5586d7972da2b5e/2_b.jpg",
      "size_list": [ 2048, 4096 ],
      "tiles": [ 1, 2, 3 ],
    },
    {
      "index": 3,
      "derived_id": 0,
      "derived_id_str": "auto3d-light-vEY8Zp4lPlkZ7R9K_1735118067",
      "up": "images/cube_2048/3/fa70f0f26594d3023a3824c9a92033da/3_u.jpg",
      "down": "images/cube_2048/3/fa70f0f26594d3023a3824c9a92033da/3_d.jpg",
      "left": "images/cube_2048/3/fa70f0f26594d3023a3824c9a92033da/3_l.jpg",
      "right": "images/cube_2048/3/fa70f0f26594d3023a3824c9a92033da/3_r.jpg",
      "front": "images/cube_2048/3/fa70f0f26594d3023a3824c9a92033da/3_f.jpg",
      "back": "images/cube_2048/3/fa70f0f26594d3023a3824c9a92033da/3_b.jpg",
      "size_list": [ 2048, 4096 ],
      "tiles": [ 1, 2, 3 ],
    },
    ...
  ]
}
```

After:
```json
"panorama": {
  "count": 465,
  "pattern": {
    "up": "images/cube_2048/{index}/{hash}/{index}_u.jpg",
    "down": "images/cube_2048/{index}/{hash}/{index}_d.jpg",
    "left": "images/cube_2048/{index}/{hash}/{index}_l.jpg",
    "right": "images/cube_2048/{index}/{hash}/{index}_r.jpg",
    "front": "images/cube_2048/{index}/{hash}/{index}_f.jpg",
    "back": "images/cube_2048/{index}/{hash}/{index}_b.jpg",
    "size_list": [ 2048, 4096 ],
    "tiles": [ 1, 2, 3]
  },
  "list": [
    {
      "hash": "0fd265355dbb94cb22fb930e52dd3c19",
      "derived_id": 0,
      "derived_id_str": "auto3d-light-vEY8Zp4lPlkZ7R9K_1735117678",
      "index": 0
    },
    {
      "hash": "a6ca1991fc6bdb2dbd1a1003d9f62394",
      "derived_id": 0,
      "derived_id_str": "auto3d-light-vEY8Zp4lPlkZ7R9K_1735117799",
      "index": 1
    },
    {
      "hash": "567f94406885bf06f5586d7972da2b5e",
      "derived_id": 0,
      "derived_id_str": "auto3d-light-vEY8Zp4lPlkZ7R9K_1735117912",
      "index": 2
    },
    {
      "hash": "fa70f0f26594d3023a3824c9a92033da",
      "derived_id": 0,
      "derived_id_str": "auto3d-light-vEY8Zp4lPlkZ7R9K_1735118067",
      "index": 3
    },
    ...
  ]
}
```

### 相对路径
> 在序列话 Work Json 时。资源的地址，均尝试存储为 `base_url` 的相对地址，减少存储的开销。

- 可以通过 `work.getURL` 获取到完整地址。
  ```ts
  // 获取图片地址
  work.getURL(work.observers[0].image.left);
  ```

- 可以通过修改 `work.baseURL=` 修改前缀。

### 一些字段的新增、废弃与兼容
- 现在 accessable_nodes 与 visible_nodes 不再有行为差异。visible_nodes 将废弃。
- observers[].derived_id 的缺损值不再是 undefiend. 而是 0。
- observers[].derived_id_str 的缺损值不再是 undefiend. 而是 空字符串。
- 优化 at3d / pbm 的 material_textures 的参数的各种兼容问题 以及 错误的警告信息。

### model 支持 coordinate 以及 up_axis
- model.coordinate 同 `tileeset.rootMeta.coordinate`。声明 `file_url` 的世界坐标。
- model.up_axis 设置 `file_url` 模型的上方向, 仅针对 obj / ply 等自身没有上方向定义的模型格式。

### toJSON 方法
- 通过 `work.toJSON()` 可以获取到当前序列化后的标准 Work Json。类型为 `WorkJson`
- 该方法并不是返回当时 `parseWork` 时的 Json。 而是从 work 数据中序列化后的结果。
- 并不包含 `_signature` `certificate` 等字段。

### work-downloader 的速度优化

- 优化 对于 avif 格式的 cube 图的处理的效率。
- 优化 全景图片瓦片的切割参数，该有尽有。
- 优化 图片的清晰度参数，目前均使用 95 最为图片质量。

## 模型优化材质展示, 3d-tile，以及碰撞计算

### glTF 模型材质 与 动画
> 优化 Gltf PBR 材质渲染。
> 对技术美术输出的模型，更准确的还原。

- 解决混合底色是白色的问题 从修改 CustomBlending 改为在着色器中处理，所以只有使用 PBM 的材质支持。three 默认材质不处理这个改动。
- 优化 gltf 骨骼绑定，对于骨骼关联大于 4 的情况，使用前 4 个权重大的骨骼，并归一化。并且考虑通过整形数组 normalize 的情况。
- 修改 gltf 中对 uv2 copy 的逻辑，添加当检测到有 occlusionTexture 材质时，如果没有 uv2 自动拷贝 uv -> uv2。

### glTF 预览工具

地址： [https://vradmin.lianjia.com/gltf/](https://vradmin.lianjia.com/gltf/)

- 支持加载 线上 / 本地文件。gltf / glb。
- 支持链接 单独的 gltf / glb 动画文件。
- 内置了 gltf 官方测试集。[https://github.com/KhronosGroup/glTF-Sample-Assets/](https://github.com/KhronosGroup/glTF-Sample-Assets/)
- 内置多个环境光照，以及上传自定义环境光照 (.exr)。

### 优化模型碰撞

扩展 threejs 的 Raycaster。 支持多个自定义参数。

```ts
declare module 'three' {

  export interface Raycaster {
    /**
     * 只捕获第一个交点
     */
    firstHitOnly?: boolean;

    /**
     * 对交点进行筛选
     */
    hitFilter?: (intersect: THREE.Intersection) => boolean;

    /**
     * 作用楼层
     */
    floorIndex?: number;
  }

}
```

- firstHitOnly - 只捕获第一个交点。比获取全部取第一个更快获取到结果。
- hitFilter - 过滤函数，可以根据逻辑否绝一些交点。配合 firstHitOnly 可以更加匹配业务需求。
- floorIndex - 过滤楼层。默认为当前显示楼层，-1 为所有楼层。其他数字则定向对应的楼层。

同时一些内部逻辑变化

- 内置事件生成的 Raycaster。均设置 firstHitOnly = true。
- 交点获取，内置过滤掉了 模型裁剪 clippers 中的内容。

### 3d-tile 支持通过内存上限动态调整 maxScreenSpaceError。
> 目的是通过有限的内存，获取到最清晰的模型效果。

```ts
// 设置内存最高缓存到 512 MB
five.modelScene.parameter.set('maxMemoryUsage', 512);

// 设置 maxScreenSpaceError 到 32
five.modelScene.parameter.set('maxScreenSpaceError', 32);

// 设置通过内存上限动态调整 maxScreenSpaceError
five.modelScene.parameter.set('memoryAdjustedScreenSpaceError', true);
```

当设置的 `maxScreenSpaceError` 已经全部加载完毕后，发现内存空间仍有剩余。则会尝试降低 `maxScreenSpaceError` 知道内存大体到达 `maxMemoryUsage` 设置的水平。

- 如果设置的 `maxScreenSpaceError` 已经全部加载完毕后，内存已经大于 `maxMemoryUsage` 设置的水平则不会变化。
- 因为是动态尝试， 所以悲观情况下会出现在 `maxMemoryUsage` 附近摆动的情况。导致模型反复加载/销毁。
- 只针对 layer 生效。多个 layer 是单独计算，并不是综合计算。

## 全景浏览

### moveToPano 新增 effect=model 模型过渡效果

通过过渡到模型实现点位游走效果

```ts
five.moveToPano(0, {
  effect: 'model',
});
```

目前支持:

- fly - 通过相机移动方式变化
- instant - 直接变化
- fade - 通过渐变方式变化
- montage - 通过渐变穿插到黑屏方式变化
- spread - 通过扩散方式变化
- zoomin - 通过放大变化
- zoomout - 通过缩小变化
- model - 通过过度到模型

### moveToPano 新增参数 effectEasing 控制前后全景图的切换进度

```ts
function easeInQuad(x: number): number {
  return x * x;
};

five.moveToPano({
  workCode: "axv2ZQMaKZcMl5Bc6x",
  panoIndex: 51,
}, {
  latitude: 0.5314685806864204,
  longitude: 4.324187623631265,
  fov: 90,
  effectEasing: easeInQuad
})
```

- effectEasing 生命一个函数，接受一个 0 到 1 的数字， 返回一个 0 到 1 的数字。
- 当值为 0 时显示前一个全景图。 为 1 时显示后一个全景图。 中间数值为两个全景图的混合， 数值表示混合比例。
- 用于 地面-天空 等切换切换占比差异较大的情况下单独设置。

### 全景图支持航拍点的差异显示

默认逻辑为:
```ts
const five = new Five({
  panorama: {
    aerialObserverMinHeight: 5,
    panoCircleMeshCreator: (observer, options) => {
      const distance = observer.position.distanceTo(observer.standingPosition);
      if (distance > options.aerialObserverMinHeight) {
        return new PanoCircleMeshSolid();
      } else {
        return new PanoCircleMesh();
      }
    },
  }
}
```
- 如果距地大于 5 米的点位为航拍点。
- 如果是航拍点，则使用 PanoCircleMeshSolid， 否则使用 PanoCircleMesh。
- 内部逻辑。航拍点会面向相机展示。

业务可以修改或介入这个逻辑。

## 渲染以及后处理

重写了渲染相关的逻辑。将 scene-renderer 和 postprocessing 分开

- scene-renderer 场景的渲染相关，需要多次渲染场景采样比如抗锯齿（aa），或者对场景内容改变，必须点云的点融合等。
- postprocessing 后处理，将 scene-renderer 的结果通过多次处理，比如轮廓增强，调整亮度等，将最终处理后的结果显示到画布上。

### 提供的 scene-renderer

- scene-renderer - 直接渲染
- point-cloud-high-quality-scene-renderer - 点云融合渲染
- ssaa-scene-renderer - SSAA算法的抗锯齿渲染

```ts
// 通过 renderMode 切换

// 直接渲染
five.renderMode = 'default';

// 点云融合渲染
five.renderMode = 'point-cloud-high-quality';

// SSAA算法的抗锯齿渲染
five.renderMode = 'ssaa';
```

### 内置后处理
- adaptive-luminance-pass - 屏幕空间动态亮度
- eye-dome-lighting-pass - 轮廓增强

```ts
// 开启 eye-dome-lighting-pass
five.enableEDL = true;

// 开启 adaptive-luminance-pass
five.enableAdaptiveLuminance = true;
```

### 自定义后处理

后处理支持 THREE 对于 后处理 Pass 的定义。可以自定义追加。

注意：目前不支持 mask 模版剔除部分的逻辑。

```ts

interface Pass {
  enabled: boolean;
  needsSwap: boolean;
  clear: boolean;
  renderToScreen: boolean;
  setSize(width: number, height: number): void;
  render(
    renderer: THREE.WebGLRenderer,
    writeBuffer: THREE.WebGLRenderTarget,
    readBuffer: THREE.WebGLRenderTarget,
    deltaTime?: number,
    maskActive?: boolean
  ): void;
}

const myPass: Pass = ...;

this.fiveRenderer.composer.addPass(myPass)
```

## 其他

- 不再使用分层渲染。enableLayeringRendering 参数废弃。
- 修复 涉嫌计算 intersectRaycaster, 如果 origin 离得太近会出现取不到的问题，优化 bvhbox 的距离判断逻辑。
- 优化近处点云碰撞时，规避掉角度大 distanceToRay / distance > 0.07 的点云。
- 修复多个 five 实例间，共用同一个 work 时 proxy 指向错误 five 实例的问题。
- 修复 mesh 模型 material.vertexMarks 没有同步 parameterValue.vertexMarks 的问题