# 機能設計書 135-Ray

## 概要

本ドキュメントは、Three.jsの数学ライブラリにおける3Dレイ（光線）を表現するRayクラスの機能設計書である。

### 本機能の処理概要

Rayクラスは、3D空間における半直線（原点から特定の方向に無限に伸びる線）を表現するためのクラスである。原点（origin）と正規化された方向ベクトル（direction）によってレイを定義し、主にRaycasterクラスでマウスピッキング（3D空間でのオブジェクト選択）や衝突検出に使用される。Three.jsにおけるインタラクション処理の基盤となる重要なクラスである。

**業務上の目的・背景**：3Dグラフィックスにおいて、レイキャスティングはマウスやタッチによるオブジェクト選択、視線追跡、衝突検出、パストレーシングなど、多くの重要な処理で使用される。Rayクラスは、これらの処理に必要なレイの数学的表現と、各種オブジェクトとの交差判定機能を提供する。

**機能の利用シーン**：
- Raycasterによるマウスピッキング（3Dオブジェクトのクリック検出）
- カメラからのビューレイ生成
- 物理シミュレーションでの衝突検出
- パストレーシングレンダリング
- 視線追跡（VR/AR）
- 弾道計算やレーザーの軌道計算

**主要な処理内容**：
1. レイの生成と初期化（原点と方向の設定）
2. 球・平面・ボックス・三角形との交差判定と交点計算
3. 点との最近点計算と距離計算
4. 線分との最短距離計算
5. レイの移動（recast）と方向変更（lookAt）
6. Matrix4による変換

**関連システム・外部連携**：Raycaster、Sphere、Plane、Box3、Triangleなどと連携。

**権限による制御**：なし（純粋な数学ユーティリティクラス）

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 2 | Viewport | 主機能 | マウスピッキングによるオブジェクト選択（Raycaster経由） |

## 機能種別

計算処理 / ジオメトリ演算

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| origin | Vector3 | No | レイの原点 | デフォルト: (0, 0, 0) |
| direction | Vector3 | No | レイの方向（正規化済み） | デフォルト: (0, 0, -1) |

### 入力データソース

コンストラクタ引数、Raycasterからの設定、またはカメラのunproject処理から生成

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| origin | Vector3 | レイの原点 |
| direction | Vector3 | レイの方向（正規化済み） |

### 出力先

メモリ上のオブジェクトとして保持

## 処理フロー

### 処理シーケンス

```
1. レイの初期化
   └─ origin=(0,0,0), direction=(0,0,-1)で初期化
2. レイの設定
   ├─ set: 直接設定
   ├─ lookAt: 方向をターゲットに向ける
   └─ recast: 原点をレイ上の点に移動
3. 交差判定・交点計算
   ├─ intersectSphere: 球との交点
   ├─ intersectPlane: 平面との交点
   ├─ intersectBox: ボックスとの交点
   └─ intersectTriangle: 三角形との交点
4. 距離計算
   ├─ distanceToPoint/distanceSqToPoint: 点との距離
   └─ distanceSqToSegment: 線分との距離
5. 最近点計算
   └─ closestPointToPoint: レイ上の最近点
6. 変換
   └─ applyMatrix4: 行列変換
```

### フローチャート

```mermaid
flowchart TD
    A[Rayインスタンス生成] --> B{設定方法}
    B -->|set| C[origin/directionを直接設定]
    B -->|lookAt| D[ターゲット方向に向ける]
    B -->|recast| E[原点をレイ上に移動]
    C --> F[レイ確定]
    D --> F
    E --> F
    F --> G{操作種別}
    G -->|交差判定| H[intersects系]
    G -->|交点計算| I[intersect系]
    G -->|距離計算| J[distanceTo/distanceSqTo系]
    G -->|最近点| K[closestPointToPoint]
    G -->|変換| L[applyMatrix4]
    I --> M{交差あり?}
    M -->|Yes| N[交点Vector3を返す]
    M -->|No| O[nullを返す]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-001 | 方向の正規化 | directionは単位ベクトルを前提 | 全操作 |
| BR-002 | パラメトリック表現 | レイ上の点 = origin + t * direction（t >= 0） | at()メソッド |
| BR-003 | 背面カリング | intersectTriangleでbackfaceCulling指定可能 | 三角形交差時 |
| BR-004 | 交点なし | 交差しない場合はnullを返す | intersect系メソッド |

### 計算ロジック

**レイ上の点の取得**:
```javascript
point = origin + direction * t  // t >= 0
```

**点との最近点**:
```javascript
directionDistance = dot(point - origin, direction)
if (directionDistance < 0) return origin  // 点がレイの後ろ
return origin + direction * directionDistance
```

**球との交差**:
```javascript
// 解の公式による二次方程式の解
oc = origin - sphere.center
a = 1 (direction is normalized)
b = 2 * dot(direction, oc)
c = dot(oc, oc) - radius^2
discriminant = b^2 - 4ac
if (discriminant < 0) return null
t = (-b - sqrt(discriminant)) / 2a
```

**三角形との交差（Moller-Trumbore法）**:
```javascript
edge1 = b - a
edge2 = c - a
normal = cross(edge1, edge2)
DdN = dot(direction, normal)
if (backfaceCulling && DdN > 0) return null
// 重心座標による内部判定
```

## データベース操作仕様

該当なし（純粋な計算処理クラス）

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | 交差なし | レイがオブジェクトと交差しない | nullを返す |
| - | 空の球 | 半径が負の球との交差判定 | falseを返す |
| - | 平行 | レイが平面に平行 | nullを返す |

### リトライ仕様

該当なし

## トランザクション仕様

該当なし

## パフォーマンス要件

- 全メソッドO(1)の計算量
- メモリ使用量: Vector3 x 2 = 48バイト程度

## セキュリティ考慮事項

該当なし（純粋な数学計算）

## 備考

- Raycasterクラスがユーザーインターフェース用のラッパーを提供
- intersectTriangleはGeometric Toolsのアルゴリズムを基にしている
- distanceSqToSegmentもGeometric Toolsのアルゴリズムを基にしている
- 背面カリングはレンダリングの最適化と同じ概念

---

## コードリーディングガイド

本機能を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

Rayクラスはorigin（Vector3）とdirection（Vector3）でレイを表現する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | Vector3.js | `src/math/Vector3.js` | Rayが依存する3Dベクトルクラス |
| 1-2 | Ray.js | `src/math/Ray.js` | クラスのプロパティ定義（origin, direction） |

**読解のコツ**: directionは必ず正規化された単位ベクトルであることを前提とする。これにより、tの値がそのまま距離を表す。

#### Step 2: 基本操作を理解する

Rayクラスの基本的な操作メソッドを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | Ray.js | `src/math/Ray.js` | set, at, lookAt, recast |

**主要処理フロー**:
1. **26-42行目**: コンストラクタでorigin/directionを初期化
2. **82-86行目**: at() - origin + direction * t でレイ上の点を取得
3. **94-100行目**: lookAt() - 方向をターゲットに向ける
4. **108-114行目**: recast() - 原点をレイ上のt位置に移動

#### Step 3: 距離計算を理解する

点や線分との距離計算ロジックを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | Ray.js | `src/math/Ray.js` | closestPointToPoint, distanceTo系, distanceSqToSegment |

**主要処理フロー**:
- **123-137行目**: closestPointToPoint() - レイ上の最近点を計算
- **157-173行目**: distanceSqToPoint() - 点がレイの後ろにある場合の処理
- **184-301行目**: distanceSqToSegment() - 線分との最短距離（複雑な領域分割アルゴリズム）

#### Step 4: 交差判定を理解する

各種オブジェクトとの交差判定・交点計算を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | Ray.js | `src/math/Ray.js` | intersect系メソッド群 |

**主要処理フロー**:
- **311-339行目**: intersectSphere() - 二次方程式による球との交差
- **362-387行目**: distanceToPlane() - 平面との距離計算
- **397-409行目**: intersectPlane() - 平面との交点
- **451-515行目**: intersectBox() - スラブ法によるAABBとの交差
- **540-613行目**: intersectTriangle() - Moller-Trumbore法による三角形との交差

#### Step 5: 三角形交差の詳細を理解する

最も複雑な三角形との交差判定アルゴリズムを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | Ray.js | `src/math/Ray.js` | intersectTriangle()の詳細 |

**主要処理フロー**:
- **546-548行目**: 三角形のエッジと法線を計算
- **555-572行目**: 背面カリングと平行判定
- **574-598行目**: 重心座標（b1, b2）の計算と範囲チェック
- **601-611行目**: t < 0の場合は交差なし

### プログラム呼び出し階層図

```
Ray
    │
    ├─ at(t, target)
    │      └─ target = origin + direction * t
    │
    ├─ closestPointToPoint(point, target)
    │      ├─ directionDistance = dot(point - origin, direction)
    │      └─ target = origin + direction * max(0, directionDistance)
    │
    ├─ intersectSphere(sphere, target)
    │      ├─ 二次方程式の判別式計算
    │      ├─ t0, t1の計算
    │      └─ at(t, target)
    │
    ├─ intersectBox(box, target)
    │      ├─ スラブ法でx, y, z軸の交差区間を計算
    │      ├─ 区間の交差チェック
    │      └─ at(tmin or tmax, target)
    │
    └─ intersectTriangle(a, b, c, backfaceCulling, target)
           ├─ edge1, edge2, normalを計算
           ├─ DdN（direction・normal）で平行判定
           ├─ 重心座標(b1, b2)を計算
           ├─ b1, b2, b1+b2の範囲チェック
           └─ at(t, target)
```

### データフロー図

```
[入力]                  [処理]                    [出力]

Sphere ────────────▶ intersectSphere() ─────▶ Vector3 | null
(球)                  (二次方程式)              (交点)

Box3 ──────────────▶ intersectBox() ─────────▶ Vector3 | null
(AABB)               (スラブ法)                (交点)

Triangle ──────────▶ intersectTriangle() ───▶ Vector3 | null
(三角形)             (Moller-Trumbore)        (交点)

Vector3[] ─────────▶ distanceSqToSegment() ──▶ number
(線分の両端)          (領域分割アルゴリズム)    (距離の二乗)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| Ray.js | `src/math/Ray.js` | ソース | レイクラス本体 |
| Vector3.js | `src/math/Vector3.js` | ソース | 3Dベクトルクラス（依存） |
| Sphere.js | `src/math/Sphere.js` | ソース | 境界球（交差判定で使用） |
| Plane.js | `src/math/Plane.js` | ソース | 平面（交差判定で使用） |
| Box3.js | `src/math/Box3.js` | ソース | 境界ボックス（交差判定で使用） |
| Matrix4.js | `src/math/Matrix4.js` | ソース | 変換行列（applyMatrix4で使用） |
| Raycaster.js | `src/core/Raycaster.js` | ソース | レイキャスティングのラッパークラス |
