# 全景图 UV 与方向转换 (Panorama UV Conversion)

- **Summary**: 提供了一组工具方法，用于在**全景图 UV 坐标** (Equirectangular UV / Cubemap UV) 与**三维空间方向向量** (Vector3) 之间进行转换。
- **Schema**: 依赖 `WorkObserver` 实例，提供四个核心转换方法。
- **Concepts**: Equirectangular Projection, Cubemap Projection, UV Origin, Coordinate Systems.
- **Configuration**: `uvOrigin` (UV 原点设置).
- **Examples**: 向量转全景 UV、UV 转向量、Cubemap 转换。

## Schema

> **Definition**: [WorkObserver](../../five/work/work.d.ts)

这些方法挂载在 `WorkObserver` 实例上，依赖当前观察点 (Observer) 的位姿信息 (Position & Quaternion) 以及 `work.transform` 进行计算。

```typescript
interface WorkObserver {
  /**
   * 将方向向量转化为全景图 uv
   * @param vector - 全局方向向量 (World Space)
   * @param uvOrigin - UV 原点位置，默认为 'top-left'
   */
  vectorToEquirectangularUv(vector: THREE.Vector3, uvOrigin?: 'top-left' | 'bottom-left'): THREE.Vector2;

  /**
   * 将全景图 uv 转化为方向向量
   * @param uv - 全景图 UV 坐标 [0, 1]
   * @param uvOrigin - UV 原点位置，默认为 'top-left'
   */
  equirectangularUvToVector(uv: THREE.Vector2, uvOrigin?: 'top-left' | 'bottom-left'): THREE.Vector3;

  /**
   * 将方向向量转化为六视图 uv
   * @param vector - 全局方向向量 (World Space)
   * @param uvOrigin - UV 原点位置，默认为 'top-left'
   */
  vectorToCubemapUv(vector: THREE.Vector3, uvOrigin?: 'top-left' | 'bottom-left'): [cubeFace: CubeFace, cubemapUv: THREE.Vector2];

  /**
   * 将六视图 uv 转化为方向向量
   * @param cubeFace - 立方体面 ('up' | 'down' | 'left' | 'right' | 'front' | 'back')
   * @param uv - 该面上的 UV 坐标 [0, 1]
   * @param uvOrigin - UV 原点位置，默认为 'top-left'
   */
  cubemapUvToVector(cubeFace: CubeFace, uv: THREE.Vector2, uvOrigin?: 'top-left' | 'bottom-left'): THREE.Vector3;
}

type CubeFace = 'up' | 'down' | 'left' | 'right' | 'front' | 'back';
```

## Concepts

### 1. 坐标系转换 (Coordinate Transformation)
转换过程会自动处理以下坐标空间的变换：
1.  **World Space (世界坐标系)**: `vector` 参数所处的坐标系。
2.  **Work Space (Work 坐标系)**: 考虑 `work.transform` 带来的整体旋转。
3.  **Observer Space (观察者坐标系)**: 考虑 `observer.quaternion` 带来的观察点旋转。
4.  **Panorama Space (全景图空间)**: 最终映射到 2D 图片上的 UV 坐标。

### 2. 投影方式 (Projection Types)
*   **Equirectangular (等距柱状投影)**: 将球体展开为 2:1 的矩形图片。常用于全景图预览。
*   **Cubemap (立方体贴图)**: 将球体投影到立方体的六个面上。常用于高清全景浏览。

### 3. UV 原点 (UV Origin)
*   **top-left (默认)**: 原点 `(0, 0)` 在图片**左上角**。U 轴向右，V 轴向下。符合大多数 Web 图片处理习惯 (Canvas, DOM)。
*   **bottom-left**: 原点 `(0, 0)` 在图片**左下角**。U 轴向右，V 轴向上。符合 WebGL / OpenGL 纹理坐标习惯。

## Configuration

所有方法均包含可选参数 `uvOrigin`。

### Common Configuration

| Parameter | Type | Default | Description |
| :--- | :--- | :--- | :--- |
| `uvOrigin` | `'top-left' \| 'bottom-left'` | `'top-left'` | 指定 UV 坐标系的原点位置。 |

## Examples

### 1. 点击全景图获取空间方向 (Click to Vector)
假设你有一个全景图的点击事件，获取到了点击位置的 UV：

```typescript
const observer = five.work.observers[0];
// 假设这是用户点击全景图后归一化得到的 UV (0~1)
const clickUv = new THREE.Vector2(0.5, 0.5);

// 转换为世界空间的方向向量
const direction = observer.equirectangularUvToVector(clickUv);

console.log('点击方向:', direction);
```

### 2. 将空间点映射到全景图上 (World Point to UV)
假设场景中有一个 3D 物体，你想知道它在当前全景图上的位置（例如打标签）：

```typescript
const observer = five.work.observers[0];
const objectPosition = new THREE.Vector3(10, 2, 5);

// 计算物体相对于观察点的方向向量
const direction = objectPosition.clone().sub(observer.position).normalize();

// 获取全景图 UV
const uv = observer.vectorToEquirectangularUv(direction);

console.log(`物体在全景图上的位置: u=${uv.x}, v=${uv.y}`);
```

### 3. 处理 Cubemap 坐标 (Cubemap Conversion)
如果你使用的是六面体全景图资源：

```typescript
const observer = five.work.observers[0];
const direction = new THREE.Vector3(0, 0, -1); // 正前方

// 获取对应的面和 UV
const [face, uv] = observer.vectorToCubemapUv(direction);

console.log(`正前方对应 Cubemap 的 ${face} 面，UV 为`, uv);
```

## Related

*   [Work](./work.md): 了解 WorkObserver 的数据结构。
*   [Coordinate System](./coordinate-system.md): 了解 Five 的坐标系定义。

---

```yaml
tags: [全景UV, 方向转换, 全景坐标, 像素映射, 全景标注, work, observer, uv, projection, math, equirectangular, cubemap]
```
