※小説ではない※専門書 要約資料集 為替(換算)3.9万円でもらう 紐解集生成 専門 初入門 資料   作:{作者名}

271 / 382
# BOOK-0227 情報派生_3DCG幾何学の実装数学 — 曲がる骨、巡る弧、分かれる枝(第2巻)

> 学問の宇宙・応用の軌道ステーション群(情報工学)派生章・情報・計算冠。ガイド役: Fable 5 監修 / Sonnet 5 執筆(脚本班)
> トーン規約: GAKUMON_UNIVERSE.md準拠。専門用語は初出で必ず説明する。水準六〜八中心。
> 前提知識: →BOOK-0226(情報派生_3DCG幾何学の実装数学_第1巻、水準五〜八)を読み終えていることを前提とする。とくに第二章(クォータニオン、ハミルト積とサンドイッチ積)・第三章(逆行列と法線変換、モデル行列の合成`M=R×S`)・第四章(レイ-平面/レイ-球交差判定)の3か所は、本書の各章が直接接続する土台であるため、読み終えていることが強く望ましい。より遠い前提として→BOOK-0071(数学派生_線形代数_第1巻、水準一〜四)の行列式`ad-bc`、→BOOK-0120(数学派生_線形代数_第2巻、水準五〜六)の対角化`P⁻¹`も、BOOK-0226を経由するかたちで本書の土台に含まれている。
> 直接の前巻: →BOOK-0226(情報派生_3DCG幾何学の実装数学_第1巻)。BOOK-0226終章「次の冊子への矢印」は、正式な続巻予告ではなく所見として、骨格アニメーション(スキニング)・球面線形補間(Slerp)の詳細な導出・空間分割によるレイキャスト高速化(BVH)という3つの話題を名指しした。本書はその所見を、正式な第2巻として実装するものである。
> 誠実な立場の明記: 本書は、CLAUDE.md「ギャップ駆動辞書拡充規約」に基づく新規GAP番号の解消を目的として書かれたものではない(該当する新規GAPエントリは本書執筆時点でdictionary_gaps.jsonに登録されていない)。本書の存在理由はそれとは別で、BOOK-0226終章が明示的に「現役の実装課題」と名指ししたにもかかわらず、名前の紹介にとどめていた3つの技術——デュアルクォータニオンスキニング、Slerpの式の導出、BVH——を、検算つきで正面から扱うことである。

---



# BOOK-0227 情報派生_3DCG幾何学の実装数学 — 曲がる骨、巡る弧、分かれる枝(第2巻)

# BOOK-0227 情報派生_3DCG幾何学の実装数学 — 曲がる骨、巡る弧、分かれる枝(第2巻)

 

> 学問の宇宙・応用の軌道ステーション群(情報工学)派生章・情報・計算冠。ガイド役: Fable 5 監修 / Sonnet 5 執筆(脚本班)

> トーン規約: GAKUMON_UNIVERSE.md準拠。専門用語は初出で必ず説明する。水準六〜八中心。

> 前提知識: →BOOK-0226(情報派生_3DCG幾何学の実装数学_第1巻、水準五〜八)を読み終えていることを前提とする。とくに第二章(クォータニオン、ハミルト積とサンドイッチ積)・第三章(逆行列と法線変換、モデル行列の合成`M=R×S`)・第四章(レイ-平面/レイ-球交差判定)の3か所は、本書の各章が直接接続する土台であるため、読み終えていることが強く望ましい。より遠い前提として→BOOK-0071(数学派生_線形代数_第1巻、水準一〜四)の行列式`ad-bc`、→BOOK-0120(数学派生_線形代数_第2巻、水準五〜六)の対角化`P⁻¹`も、BOOK-0226を経由するかたちで本書の土台に含まれている。

> 直接の前巻: →BOOK-0226(情報派生_3DCG幾何学の実装数学_第1巻)。BOOK-0226終章「次の冊子への矢印」は、正式な続巻予告ではなく所見として、骨格アニメーション(スキニング)・球面線形補間(Slerp)の詳細な導出・空間分割によるレイキャスト高速化(BVH)という3つの話題を名指しした。本書はその所見を、正式な第2巻として実装するものである。

> 誠実な立場の明記: 本書は、CLAUDE.md「ギャップ駆動辞書拡充規約」に基づく新規GAP番号の解消を目的として書かれたものではない(該当する新規GAPエントリは本書執筆時点でdictionary_gaps.jsonに登録されていない)。本書の存在理由はそれとは別で、BOOK-0226終章が明示的に「現役の実装課題」と名指ししたにもかかわらず、名前の紹介にとどめていた3つの技術——デュアルクォータニオンスキニング、Slerpの式の導出、BVH——を、検算つきで正面から扱うことである。

 

---

 

## 一枚要約(本書の地図)

 

**目的**: BOOK-0226が「名前の紹介にとどめた」3つの技術——骨格アニメーション(スキニング)とその古典的弱点(キャンディラップ問題)、Slerpの式の幾何学的導出、BVHによるレイキャスト高速化——を、検算つきで正面から扱い、前巻が開けたままにした3つの扉を閉じること。

 

**得られる力**: 本書を読み終えると、ボーン(骨)の親子階層をどう1本の行列の連鎖として合成するか、リニアブレンドスキニング(LBS)で頂点をどう複数のボーンから重み付きで変形させるか、その古典的な弱点である「キャンディラップ問題」がなぜ・どれくらい起きるのかを具体的な数値で説明できるようになる。Slerpの式`Slerp(q1,q2,t) = (sin((1-t)θ)/sinθ)q1 + (sin(tθ)/sinθ)q2`がどこから来るのかを、単位球面上の等角速度補間という発想から自分で導出できるようになる。そして、シーン内の物体が数千・数万に増えたとき、なぜBVHが総当たりの線形探索よりずっと速いのかを、具体的な計算量の数値で説明できるようになる。

 

**再利用可能性**: 本書で確立するボーン階層・LBS・Slerp導出・BVHの基礎は、ゲームEditor本体のキャラクターアニメーション機能、カメラワークやカットシーンの補間、原画班が扱う大規模シーンでのオブジェクト選択・衝突判定などで、今後BOOK-0226と並ぶ共通言語として再利用される想定である。またFUNC辞書側(コード生成カード側)が将来アニメーション・空間分割ドメインを新設する際の理論的出典としても参照できる。

 

**目次**: 第一章 骨格アニメーション(スキニング)/第二章 球面線形補間(Slerp)の詳細な導出/第三章 空間分割によるレイキャスト高速化(BVH)/実装のこつ集/終章/章末簡易階段図/参照文献。

 

---

 

## 前提知識マップ — 5冊の関係(系統ではなく橋渡しの位置づけ)

 

本書はBOOK-0226と同じく、数学冠(BOOK-0071・BOOK-0120)と造形工学系統(BOOK-0187)という異なる系統をまたいで橋渡しする、情報・計算冠の派生巻である。そのため以下は正式な「系統水準表」ではなく、BOOK-0226が示した4冊の地図に本書を書き足した、5冊の前提知識マップとして示す。

 

```

┌──────────────────────────────────────────────────────────────────────┐

│ BOOK-0227 前提知識マップ(5冊の関係・水準一 ──────────→ 水準八) │

├──────────────────────────────────────────────────────────────────────┤

│ BOOK-0071 数学派生_線形代数_第1巻(水準一〜四) │

│ ベクトル・行列・行列式ad-bc・固有値の入口 │

│ ─●●●●─────────────────────────────────── │

│ │

│ BOOK-0120 数学派生_線形代数_第2巻(水準五〜六) │

│ 対角化・スペクトル定理・逆行列の記号P⁻¹が初登場 │

│ ─────●●────────────────────────────────── │

│ │

│ BOOK-0187 額縁から景色へ_射影の数式と3DCG構造史(水準四〜八) │

│ カメラ座標→スクリーン座標(片道)・同次座標・ビューイングパイプライン │

│ ───●●●●●●●●───────────────────────── │

│ │

│ BOOK-0226 情報派生_3DCG幾何学の実装数学_第1巻(水準五〜八) │

│ 外積・クォータニオン・逆行列と法線変換・レイキャスト(逆方向)・ │

│ ジオメトリ生成/BVHとSlerpの式は名前の紹介にとどめる │

│ ─────●●●●●●●●─────────────────────── │

│ │

│ BOOK-0227 本書(水準六〜八) │

│ 骨格アニメーション(スキニング)・Slerpの導出・BVHによる高速化 │

│ ───────●●●●●●●●───────────────── │

└──────────────────────────────────────────────────────────────────────┘

```

 

BOOK-0071とBOOK-0120が「数の表をどう計算するか」という一般論を、BOOK-0187が「カメラ座標を一方向にスクリーンへ落とし込む数式」を、BOOK-0226が「クリックの先の世界へ手を伸ばす」ための道具一式を、それぞれ担当してきた。本書はその先——道具箱がそろったあとに実際に必要になる「動かす」「滑らかに移す」「たくさんの物体から絞り込む」という3つの実務上の要請——を担当する。

 

---

 

## 講師からの前書き — 額縁の外で、腕を曲げ、弧を描き、枝を分ける

 

前巻BOOK-0226は、「クリックの先にある世界」への手の伸ばし方——スクリーンの1点から、3D空間のどの物体を選んだかを計算で当てる方法——を検算つきで確立した。しかし、その世界にひとたび手が届いたなら、次の問いは自然に生まれてくる。

 

選ばれたキャラクターは、どうやって腕を曲げ、歩き、剣を振るのか(骨格アニメーション)。カメラやキャラクターの構えが、ある姿勢から別の姿勢へ移り変わるとき、その「あいだ」はどんな道筋をたどるべきなのか(球面線形補間、Slerp)。そして、選ぶべき候補が1個や2個ではなく数万個に達したとき、いちいち全部と交差判定していては到底間に合わなくなる——では、調べるべき物体をどうやってすばやく絞り込むのか(BVH)。

 

この3つの問いは、偶然にもすべて「BOOK-0226が名前だけ挙げて、深入りしなかった」話題である。第二章2-7節はSlerpの存在と利点(Shoemake, 1985)を紹介したが、式の中身までは踏み込まなかった。第四章の深掘りコラムは、物体数が増えたときの高速化の必要性に触れながら、「この高速化技法自体は本書の範囲を超えるため、ここでは名前の紹介にとどめる」と明言していた。そして章末の階段図は、デュアルクォータニオンによるスキニングを「現役の実装課題」と名指ししながら、その先には踏み込まなかった。

 

本書は、この3つの「保留」に、それぞれ決着をつける。第一章では、BOOK-0226第三章が検算した「2つの行列の合成`M=R×S`」を、2個ではなくN個の行列の連鎖へと一般化し、骨格アニメーションの土台を作る。そのうえでリニアブレンドスキニング(LBS)の数式を導入し、実装の現場で必ず一度はぶつかる古典的な弱点——キャンディラップ問題——を、具体的な数値で「どれだけ体積が失われるか」まで検算する。第二章では、BOOK-0226が名前だけ挙げていたSlerpの式を、単位球面上を一定の角速度で進む、という幾何学的な発想から自分の手で導出し、なぜ素朴な線形補間では速度にムラが出るのかを、同じくBOOK-0226の検算例を使って数値で確かめる。第三章では、BOOK-0226第四章のレイ-平面・レイ-球交差判定を土台に、物体の数が数万に達したときの高速化技法——BVH——を、その構築(バウンディングボリュームの合成)と走査(枝刈り)の両面から、具体的な数値とともに扱う。

 

数値の検算を惜しまないという約束は、BOOK-0226から変わらない。額縁の外に出た世界で、今度は実際に、骨を曲げ、弧を描き、枝を分けていこう。

 

---

 

## 休憩所ゼロ: まとめ箱 — 前書きのポイント

 

```

本書の出自: BOOK-0226終章の「所見」(正式な続巻予告ではない)を、正式な第2巻として実装したもの

扱う3つの保留: ①スキニングとキャンディラップ問題 ②Slerpの式の導出 ③BVHによる高速化

 

旅程: 骨格アニメーション(BOOK-0226第三章の行列合成をN個の骨へ一般化)

→ Slerpの導出(単位球面上の等角速度補間という発想から式を導く)

→ BVH(BOOK-0226第四章のレイ交差判定に、空間分割による枝刈りを足す)

```

 

---

 

## 第一章: 骨格アニメーション(スキニング) — 骨を曲げ、皮膚を追従させる

 

### 1-1. ボーンとは何か、階層とは何か

 

3Dキャラクターを動かすとき、頂点(BOOK-0226第五章)を1つ1つ手作業でアニメーションさせるのは非現実的である。実務では、キャラクターの内部に**ボーン(骨、bone、水準六: 3Dキャラクターの内部に仮想的に配置される、位置・向きを持つ棒状の制御点。実際の骨のような形状データは持たず、頂点を変形させるための「操り手」として働く)**と呼ばれる制御構造を埋め込み、頂点をボーンに結び付けて動かす。これを**スキニング(skinning、水準六: ボーンの動きに応じて、メッシュ〈頂点の集まり〉の表面〈皮膚〉を追従させて変形させる技術)**と呼ぶ。

 

ボーンは単独では存在せず、**骨格(スケルトン、skeleton、水準六: 複数のボーンが親子関係でつながった、木構造の集まり)**という形で、親子関係を持つ**階層(かいそう、hierarchy)**を構成する。人体の腕を例にとれば、肩のボーンが親、肘のボーンがその子、手首のボーンがさらにその子、という具合である。子ボーンは親ボーンに対する**相対的な変換(ローカル変換)**だけを持ち、実際にワールド空間(あるいはメッシュ空間)でどこにあるかという**グローバル変換**は、祖先のローカル変換をすべて連鎖的に掛け合わせることで求まる。

 

```

あるボーンのグローバル変換 = 親のグローバル変換 × 自分のローカル変換

```

 

この式に見覚えがある読者は正しい。→BOOK-0226 第三章3-5節は、モデル行列`M`を「90度回転`R`と非一様スケーリング`S`の合成」`M=R×S`として検算した。ボーン階層のグローバル変換は、この「2つの行列の合成」を、2個ではなく、ルートから末端まで続くN個の行列の連鎖へと一般化したものにほかならない。BOOK-0226が確立した「行列の合成」という道具は、そのままボーン階層の理論的な土台になる。

 

### 1-2. 同次座標のおさらいと、2ボーンの腕モデル

 

回転だけでなく平行移動も1つの行列にまとめて扱うため、→BOOK-0187第三章が導入した**同次座標(どうじざひょう、点に4番目の成分`w=1`を追加し、平行移動も行列の掛け算として表現できるようにする技法)**の発想を、ここでも使う。2次元の点`(x,y)`を`(x,y,1)`という3成分に拡張すれば、3×3の行列1つで、回転と平行移動を同時に表せる。

 

```

回転(角度θ) = [ cosθ -sinθ 0 ; sinθ cosθ 0 ; 0 0 1 ]

平行移動(tx,ty) = [ 1 0 tx ; 0 1 ty ; 0 0 1 ]

```

 

以降、本章では2次元の**2ボーンの腕モデル**を狂言回しに使う(→BOOK-0226 3-5節が「3次元でも考え方はまったく同じである」として2次元で検算を行った先例に倣う)。

 

```

ボーン1(上腕): バインドポーズ(基準姿勢)で原点(0,0)から(2,0)まで、回転なし

ボーン2(前腕): バインドポーズでボーン1の先端(2,0)から(4,0)まで、ボーン1に対する相対回転なし

```

 

ボーン1はルートなので、バインドポーズでのグローバル変換`B1`は単位行列である。ボーン2のローカル変換(ボーン1から見た相対位置)は「(2,0)だけ平行移動」であり、バインドポーズでのグローバル変換`B2`は、`B1`と合成して`B2 = 平行移動(2,0)`となる(ボーン2の原点は、ちょうどボーン1の先端(2,0)に一致する)。

 

### 1-3. 検算: 肩を90度回転させ、腕全体が正しく連動するかを確かめる

 

肩(ボーン1)を原点まわりに90度回転させたとき、肘から先の前腕(ボーン2)が正しく連動するかを検算しよう。ボーン2のローカル変換は変えない(肘は曲げず、腕全体が剛体として回転する状況)。

 

```

R90 = [ 0 -1 0 ; 1 0 0 ; 0 0 1 ] (90度回転、→BOOK-0226 3-5節のRと同じ行列)

T(2,0) = [ 1 0 2 ; 0 1 0 ; 0 0 1 ] (ボーン2のローカル平行移動)

 

ボーン1のグローバル変換(アニメ後): M1 = R90

ボーン2のグローバル変換(アニメ後): M2 = M1 × T(2,0) = R90 × T(2,0)

```

 

行列の積を成分ごとに計算すると、

 

```

M2 = R90 × T(2,0) = [ 0 -1 0 ; 1 0 2 ; 0 0 1 ]

```

 

これが正しいかを、具体的な点で検算する。まず、ボーン2の原点(肘の位置、ローカル座標`(0,0,1)`)がどこへ移るか。

 

```

M2 × (0,0,1) = (0×0+(-1)×0+0×1, 1×0+0×0+2×1, 1) = (0, 2, 1) → 肘の位置 (0, 2)

```

 

バインドポーズで肘は`(2,0)`にあった。90度回転させれば`(x,y)→(-y,x)`の関係により`(2,0)→(0,2)`となるはずであり、ちょうど一致する。次に、前腕の先端(手首、ローカル座標`(2,0,1)`)がどこへ移るかも確かめる。

 

```

M2 × (2,0,1) = (0×2+(-1)×0+0×1, 1×2+0×0+2×1, 1) = (0, 4, 1) → 手首の位置 (0, 4)

```

 

バインドポーズでの手首`(4,0)`を90度回転させると`(4,0)→(0,4)`となり、これもちょうど一致する。肘を曲げていないので腕全体が1本の剛体として回転し、その通りの結果が得られたことが検算できた。「親のグローバル変換×自分のローカル変換」という連鎖のルールが、正しく機能していることが確認できる。

 

### 1-4. リニアブレンドスキニング(LBS)の数式

 

腕の「骨」は分かったので、次は「皮膚」——実際にメッシュの頂点をどう変形させるかに進もう。最も広く使われる手法が**リニアブレンドスキニング(りにあぶれんどすきにんぐ、線形ブレンドスキニング、Linear Blend Skinning、LBS、水準六: 各頂点を複数のボーンに関連づけ、それぞれのボーンによる変形結果を、あらかじめ決めた重みで足し合わせて最終的な頂点位置を求める手法)**である。

 

1本のボーンだけに完全に結び付いた頂点なら話は簡単だが、肘や肩の周りの皮膚は、隣り合う2本(あるいはそれ以上)のボーンの両方から影響を受けるのが自然である。LBSはこれを次の式で扱う。

 

```

v' = Σᵢ wᵢ × (Mᵢ × Bᵢ⁻¹ × v)

```

 

ここで`v`はバインドポーズでの頂点位置、`Mᵢ`はボーン`i`の現在(アニメーション後)のグローバル変換、`Bᵢ`はボーン`i`のバインドポーズでのグローバル変換、`wᵢ`はボーン`i`がその頂点に与える重み(スキンウェイト、`Σᵢwᵢ=1`となるよう正規化される)である。

 

注目すべきは`Bᵢ⁻¹`——→BOOK-0226第三章で確立した**逆行列**が、ここで実際に使われている点である。`Bᵢ⁻¹`は「バインドポーズでのボーンの変換を打ち消し、頂点をそのボーンのローカル座標系に引き戻す」役割を持つ**バインド逆行列(ばいんどぎゃくぎょうれつ、inverse bind matrix、水準六: バインドポーズでのボーンのグローバル変換の逆行列。頂点をメッシュ空間からボーンのローカル空間へ戻すために使う)**である。`v`をいったんボーン`i`のローカル座標に戻し(`Bᵢ⁻¹×v`)、それから現在のボーンの姿勢`Mᵢ`を掛け直すことで、「そのボーンに完全に追従した場合の頂点位置」が求まる。これを全ボーンについて重み付きで足し合わせたものが、LBSの最終結果である。

 

### 1-5. 検算: LBSによる頂点の重み付き合成(90度の肘曲げ)

 

具体的な数値で確かめよう。1-2節の2ボーンモデルに戻り、今度は肩(ボーン1)は動かさず(`M1=単位行列`)、肘(ボーン2のローカル変換)だけを90度曲げる。

 

ボーン2のローカル変換(アニメ後)は、まず自分自身の原点を中心に90度回転し、そのあとで肩からの取り付け位置`(2,0)`へ平行移動する、という順序で合成する。

 

```

Local2(90°) = T(2,0) × R90 = [ 0 -1 2 ; 1 0 0 ; 0 0 1 ]

M2(90°) = M1 × Local2(90°) = Local2(90°) (M1=単位行列のため)

```

 

肘の位置(ボーン2の原点)がバインドポーズと変わっていないことを確認しておく。`M2(90°) × (0,0,1) = (2, 0, 1)` → 肘は`(2,0)`のまま(肩を動かしていないので当然である)。

 

次に、肘の少し上の皮膚を表す頂点`v=(2,1)`(バインドポーズで、肘の関節から見て垂直方向に1だけ離れた点)を考える。バインド逆行列は`B1⁻¹=単位行列`、`B2⁻¹=平行移動(-2,0)`である。

 

```

ボーン1だけに100%従った場合: M1 × (B1⁻¹ × v) = 単位行列 × (2,1,1) = (2, 1)

ボーン2だけに100%従った場合: M2(90°) × (B2⁻¹ × v)

B2⁻¹×v = 平行移動(-2,0) × (2,1,1) = (0, 1, 1)

M2(90°) × (0,1,1) = (0×0+(-1)×1+2×1, 1×0+0×1+0×1, 1) = (1, 0)

```

 

ボーン1だけに従えば`(2,1)`のまま、ボーン2だけに従えば`(1,0)`——2つの答えが食い違う。ここでLBSは、重み`w1=0.5, w2=0.5`(肘のちょうど中間にある皮膚として、両方から均等に影響を受けると仮定する)で、この2つを線形に合成する。

 

```

v' = 0.5×(2,1) + 0.5×(1,0) = (1.5, 0.5)

```

 

重みの合計`w1+w2=0.5+0.5=1`が保たれていることも確認できる(重みの合計が1でなければ、頂点が伸び縮みしてしまう)。この`(1.5, 0.5)`が、90度の肘曲げにおけるLBSの結果である。肘の関節`(2,0)`からのこの点の距離を計算すると、

 

```

距離 = √((1.5-2)² + (0.5-0)²) = √(0.25+0.25) = √0.5 ≈ 0.7071

```

 

バインドポーズでこの頂点は関節から距離1(`v=(2,1)`、関節`(2,0)`との差は`(0,1)`で長さ1)にあった。90度曲げただけで、すでに距離が1から約0.7071へと縮んでいる。次節では、この「距離が縮む」現象がどこまで進むかを見る。

 

### 1-6. キャンディラップ問題 — LBSの古典的弱点

 

前節で見た「距離が縮む」現象を、極端な角度まで押し進めるとどうなるかを検算しよう。肘を90度ではなく、180度(前腕を完全に折りたたむ)まで曲げてみる。

 

```

Local2(180°) = T(2,0) × R180 = [ -1 0 2 ; 0 -1 0 ; 0 0 1 ]

(R180 = [ -1 0 0 ; 0 -1 0 ; 0 0 1 ])

M2(180°) = Local2(180°) (M1=単位行列のため)

```

 

肘の位置は`M2(180°)×(0,0,1) = (2,0,1)`で、やはり`(2,0)`のまま変わらない(肩は動かしていない)。前腕の先端(手首、ローカル`(2,0,1)`)は`M2(180°)×(2,0,1) = (-1×2+0+2, 0-0+0, 1) = (0,0,1)`——手首がちょうど肩の位置`(0,0)`まで折り返され、腕が完全に自分自身の上に折り重なった状態になる。180度の折り曲げとして、これは幾何学的に正しい。

 

同じ頂点`v=(2,1)`について、ボーン1・ボーン2それぞれに100%従った場合を計算する。

 

```

ボーン1だけ: (2, 1) (肩は動いていないので、変化なし)

ボーン2だけ: M2(180°) × (B2⁻¹×v) = M2(180°) × (0,1,1) = (-1×0+0×1+2×1, 0×0+(-1)×1+0×1, 1) = (2, -1)

```

 

LBSで50/50合成すると、

 

```

v' = 0.5×(2,1) + 0.5×(2,-1) = (2, 0)

```

 

得られた点`(2,0)`は、**関節そのものの位置**である。関節からの距離を計算すると、

 

```

距離 = √((2-2)²+(0-0)²) = 0

```

 

バインドポーズで距離1だった頂点が、180度の折り曲げによって、距離**0**——関節上の1点にまで完全に押し潰されてしまった。これが**キャンディラップ問題(candy wrapper problem、水準六: LBSで関節を大きく曲げたとき、関節周りの皮膚が、キャンディの包み紙をひねったときのように、関節に向かって断面ごと絞り込まれて潰れてしまう古典的な弱点)**である。180度という極端な角度は誇張だが、90度・180度という2つの検算結果を並べると、この現象が角度とともにどう進行するかが見えてくる。

 

```

0度(曲げなし): 距離 = 1 (r・cos(0°/2) = 1×1 = 1)

90度: 距離 ≈ 0.7071 (r・cos(90°/2) = 1×cos45° ≈ 0.7071)

180度: 距離 = 0 (r・cos(180°/2) = 1×cos90° = 0)

```

 

実はこの2つの検算結果は、`距離 = r・cos(φ/2)`(`r`=バインドポーズでの関節からの距離、`φ`=曲げ角度)という一般式にきれいに一致する。この式は、大きさが等しく角度`φ`だけ開いた2本のベクトルを均等(50/50)に合成すると、合成後の長さは元の長さの`cos(φ/2)`倍になる、というベクトルの平行四辺形則から導かれる(`|0.5v1+0.5v2|² = 0.25(|v1|²+|v2|²+2v1・v2) = 0.25(2r²+2r²cosφ) = r²(1+cosφ)/1 = r²×2cos²(φ/2)`……ではなく正しくは`r²(1+cosφ)=2r²cos²(φ/2)`の関係〈半角公式`1+cosφ=2cos²(φ/2)`〉を使うと`|0.5v1+0.5v2|=r・cos(φ/2)`となる)。曲げ角度`φ`が大きくなるほど`cos(φ/2)`は0に近づき、関節周りの皮膚がどんどん痩せ細っていくことが、この式からも裏付けられる。

 

### 深掘りコラム: デュアルクォータニオンスキニング — 回転と平行移動を1つの数で

 

キャンディラップ問題が起きる根本原因は、LBSが「**位置**(カルテシアン座標の点)」を直接、線形に(=ベクトルの単純な平均で)ブレンドしていることにある。関節が大きく曲がるほど、2つの剛体変換の結果である2つの位置は互いに離れていき、その単純な平均は、正しい(回転を反映した弧を描くような)中間位置からどんどん外れて、関節の内側へ向かって縮んでしまう。

 

この問題への現役の対策が、BOOK-0226終章が名指しした**デュアルクォータニオンスキニング(でゅあるくぉーたにおんすきにんぐ、Dual Quaternion Skinning、DQS、水準八: 回転と平行移動を1つの8成分の数〈デュアルクォータニオン〉で統一的に表現し、その数そのものをブレンドすることで、位置を直接平均するLBSより自然な変形を得る手法)**である。

 

その土台になるのが**二重数(にじゅうすう、dual number、水準八: `a+bε`という形の数。`ε`は`ε²=0`(ただし`ε`自身は0ではない)という特殊な性質を持つ記号で、`ε`のべき乗はすぐに消えてしまう)**である。→BOOK-0226第二章2-3節は、ハミルトンが複素数`a+bi`(`i²=-1`)を拡張してクォータニオンを発見した経緯を紹介した。二重数はこれとよく似た発想で、複素数の`i²=-1`の代わりに`ε²=0`という規則を採用した、別の数の拡張である。

 

**デュアルクォータニオン**は、この`ε`を使って、2つの通常のクォータニオン(→BOOK-0226第二章)を1つにまとめたものである。

 

```

q̂ = q_r + ε・q_d

```

 

`q_r`(実部、回転クォータニオン)は、→BOOK-0226第二章がそのまま扱ったのと同じ、回転を表す単位クォータニオンである。`q_d`(双対部)には平行移動の情報が、次の式でエンコードされる。

 

```

q_d = (1/2) × t_quat × q_r (t_quat = (0, tx, ty, tz)、平行移動ベクトルを純粋クォータニオンとして表したもの)

```

 

**検算(平行移動のみのエンコード/デコード)**: 回転なし(`q_r=(1,0,0,0)`)、平行移動`(2,0,0)`だけの単純な場合で確かめる。→BOOK-0226第二章2-4節のハミルト積の式に代入すると、

 

```

t_quat × q_r = (0,2,0,0) × (1,0,0,0) = (0,2,0,0) (q_rが単位クォータニオンで恒等回転のため、掛けても変化しない)

q_d = 0.5 × (0,2,0,0) = (0,1,0,0)

```

 

逆に、この`q̂ = (1,0,0,0) + ε(0,1,0,0)`から平行移動を取り出す式`t_quat = 2 × q_d × q_r*`(`q_r*`は共役、→BOOK-0226 2-5節)を使うと、

 

```

q_r* = (1,0,0,0) (恒等回転の共役は自分自身)

q_d × q_r* = (0,1,0,0) × (1,0,0,0) = (0,1,0,0)

t_quat(復元) = 2 × (0,1,0,0) = (0,2,0,0) → 平行移動 (2,0,0)

```

 

元の平行移動`(2,0,0)`が、符号の狂いなく正確に復元された。回転と平行移動という異質な2つの情報を、たった8つの数(実部4つ+双対部4つ)の中に、矛盾なく折りたたんで保存できることが、この単純な例からも確認できる。

 

デュアルクォータニオンスキニングは、このデュアルクォータニオンそのものを(位置ではなく)ブレンドし、そのあとで頂点に適用する。回転の情報が最後まで「回転として」保持されるため、LBSのように2つの位置を直接平均することによる、関節の痩せ細り(キャンディラップ問題)が大幅に緩和されることが知られている(ただし、完全な万能薬ではなく、大きく捻った関節では別の種類のわずかな膨らみ〈bulging〉が生じる場合があることも指摘されている)。ブレンドの具体的な計算式(正規化を含む)は本書の範囲を超えるため、概要の紹介にとどめる。

 

---

 

## 休憩所①: まとめ箱 — 第一章のポイント

 

```

ボーン階層: グローバル変換 = 親のグローバル変換 × 自分のローカル変換

(BOOK-0226 3-5節「M=R×S」の2行列合成を、N個の連鎖へ一般化したもの)

検算: 肩を90度回転(肘は曲げない)→肘(0,2)・手首(0,4)、バインドポーズを90度回転させた値と完全一致

 

LBS: v' = Σᵢ wᵢ×(Mᵢ×Bᵢ⁻¹×v) Bᵢ⁻¹はバインド逆行列(BOOK-0226第三章の逆行列の応用)

検算: 90度の肘曲げ、v=(2,1)→ボーン1のみ(2,1)/ボーン2のみ(1,0)→50/50合成で(1.5,0.5)、関節距離1→0.7071

 

キャンディラップ問題: 180度の極端な例でv'=(2,0)、関節距離が1→0へ完全崩壊

一般式: 距離=r・cos(φ/2)(φ=曲げ角度)。0度→1、90度→0.7071、180度→0、と検算が一致

 

深掘り: デュアルクォータニオン q̂=q_r+ε・q_d(ε²=0の二重数)。平行移動(2,0,0)のエンコード/デコードを検算し、

元の値が正確に復元されることを確認。位置でなく変換そのものをブレンドすることで痩せ細りを緩和する。

```

 

---

 

## 第二章: 球面線形補間(Slerp)の詳細な導出 — なぜその式なのか

 

### 2-1. BOOK-0226が素通りしたもの

 

→BOOK-0226第二章2-7節は、クォータニオンがオイラー角に対して持つ3つの利点の1つとして、Slerp(球面線形補間)の存在を紹介した。「数学者ケン・シューメイク(Ken Shoemake)が1985年の論文でコンピュータグラフィックスに導入したとされるこの手法により、カメラワークやキャラクターの姿勢変化を、不自然な速度のムラなく滑らかに繋ぐことができる」——ここまでがBOOK-0226の記述であり、式`Slerp(q1,q2,t) = (sin((1-t)θ)/sinθ)q1 + (sin(tθ)/sinθ)q2`そのものがどこから来るのかは、示されていなかった。本章はその式を、自分の手で導出する。

 

### 2-2. 単位球面上の等角速度補間という発想

 

クォータニオンは4つの成分`(w,x,y,z)`を持つが、**単位クォータニオン**(回転を表すもの)は常に`w²+x²+y²+z²=1`を満たす。これは、4次元空間の中にある「半径1の球面(4次元の球面なので、3次元の私たちの直感的な球面とは次元が違うが、性質は類似している)」の上の1点として、単位クォータニオンを捉えられることを意味する。

 

2つの単位クォータニオン`q1`・`q2`を、この4次元の単位球面上の2点とみなすと、その間には**測地線(そくちせん、geodesic、水準七: 球面のような曲がった空間の上で、2点を結ぶ最短経路。平面での「直線」に相当するもの)**——より具体的には、球の中心を通る平面と球面が交わってできる**大円(だいえん、great circle)**の弧——がただ1つ(対蹠点でない限り)定まる。

 

Slerpとは、この大円弧の上を、**一定の角速度**(単位時間あたり進む角度が常に同じ)で`q1`から`q2`まで動く補間のことである。「一定の角速度で進む」という条件が、Slerpを、あとで見る素朴な線形補間から区別する核心である。

 

### 2-3. 導出: Slerpの式を導く

 

`q1`と`q2`のなす角(4次元空間での内積による角度)を`θ`とする。

 

```

cosθ = q1 · q2 (4成分の内積、通常のベクトルの内積と同じ計算)

```

 

`q1`から出発し、`q1`に直交する(そして`q1`・`q2`が張る2次元平面の中にある)単位ベクトル`q_perp`を使うと、この大円弧上を一定角速度で動く点は、次のように書ける。

 

```

q(t) = q1・cos(tθ) + q_perp・sin(tθ)

```

 

これは、2次元平面上の単位円を、角度`tθ`だけ進んだ点の座標そのものである(`cos²+sin²=1`により、`|q(t)|=1`が保たれることも保証される)。`t=0`で`q(0)=q1`(正しい)。`t=1`で`q1`から`q2`にちょうど到達してほしいので、`q(1)=q1・cosθ + q_perp・sinθ = q2`という関係が成り立つはずである。これを`q_perp`について解くと、

 

```

q_perp = (q2 - q1・cosθ) / sinθ

```

 

これを`q(t)`の式に代入する。

 

```

q(t) = q1・cos(tθ) + [(q2 - q1・cosθ)/sinθ]・sin(tθ)

= q1・[cos(tθ) - cosθ・sin(tθ)/sinθ] + q2・[sin(tθ)/sinθ]

= q1・[(cos(tθ)・sinθ - cosθ・sin(tθ)) / sinθ] + q2・[sin(tθ)/sinθ]

```

 

ここで、三角関数の**加法定理(角度の引き算の公式)**`sin(A-B) = sinA・cosB - cosA・sinB`を、`A=θ, B=tθ`として使うと、`sinθ・cos(tθ) - cosθ・sin(tθ) = sin(θ-tθ) = sin((1-t)θ)`とちょうど一致する。したがって、

 

```

q(t) = [sin((1-t)θ)/sinθ]・q1 + [sin(tθ)/sinθ]・q2

```

 

これが求めたいSlerpの式そのものである。単位球面上を一定角速度で進む、という幾何学的な要請だけから、この式が自然に導かれることが確認できた。

 

### 2-4. 検算: 導出過程の三角関数恒等式を数値で確認

 

前節の導出の鍵になった等式`sinθ・cos(tθ) - cosθ・sin(tθ) = sin((1-t)θ)`を、具体的な数値で検算しておこう。`θ=45°`、`t=0.25`とすると、`(1-t)θ=33.75°`、`tθ=11.25°`である。

 

```

左辺 = sin(45°)×cos(11.25°) - cos(45°)×sin(11.25°)

= 0.70711×0.98079 - 0.70711×0.19509

= 0.70711×(0.98079-0.19509)

= 0.70711×0.78570

≈ 0.55557

 

右辺 = sin(33.75°) ≈ 0.55557

```

 

両辺が一致し、導出の途中で使った加法定理が正しく機能していることが検算できた。

 

### 2-5. 検算: BOOK-0226の検算例を使ってSlerpを計算する

 

→BOOK-0226第二章2-6節は、`z`軸まわり90度回転を表す単位クォータニオン`q=(√2/2,0,0,√2/2)≈(0.7071,0,0,0.7071)`を検算していた。この値をそのまま再利用し、`q1=(1,0,0,0)`(恒等回転、0度)、`q2=(0.7071,0,0,0.7071)`(90度回転)の間をSlerpで補間してみよう。

 

```

cosθ = q1・q2 = 1×0.7071 + 0 + 0 + 0×0.7071 = 0.7071 → θ = 45°

```

 

**t=0.5(中間点)の検算**:

 

```

Slerp(0.5) = [sin(22.5°)/sin(45°)]×q1 + [sin(22.5°)/sin(45°)]×q2

= 0.54120×(1,0,0,0) + 0.54120×(0.7071,0,0,0.7071)

= (0.54120+0.38268, 0, 0, 0.38268)

= (0.9239, 0, 0, 0.3827)

```

 

`q1`と`q2`はどちらも`z`軸まわりの回転(回転軸が共通、いわゆる「同軸」の関係)なので、この結果は「45度回転(90度の半分)」を表す`(cos22.5°,0,0,sin22.5°)=(0.9239,0,0,0.3827)`と一致するはずであり、実際に一致した。さらに`|Slerp(0.5)|=√(0.9239²+0.3827²)=√(0.8536+0.1464)=√1.0=1`と、単位クォータニオンであることも保たれている。

 

**t=0.25の検算**:

 

```

Slerp(0.25) = [sin(33.75°)/sin(45°)]×q1 + [sin(11.25°)/sin(45°)]×q2

= 0.78570×(1,0,0,0) + 0.27590×(0.7071,0,0,0.7071)

= (0.78570+0.19509, 0, 0, 0.19509)

= (0.9808, 0, 0, 0.1951)

```

 

同軸の回転どうしのSlerpは角度を単純に線形補間するはずなので、`t=0.25`は「22.5度回転(90度の1/4)」`(cos11.25°,0,0,sin11.25°)=(0.9808,0,0,0.1951)`と一致するはずであり、これも実際に一致した。

 

### 2-6. なぜ単純な線形補間では速度が不均一になるのか — 検算

 

前巻でも触れなかった問いに、ここで決着をつける。もし式の煩雑さを嫌って、単純な線形補間`(1-t)q1 + t・q2`(このあと必要に応じて長さ1へ正規化する手法は**Nlerp(正規化線形補間、Normalized Linear Interpolation)**と呼ばれる)を使ったら、何が問題になるのか。

 

`t=0.25`で、まず正規化前の生の値を計算する。

 

```

raw = 0.75×(1,0,0,0) + 0.25×(0.7071,0,0,0.7071) = (0.9268, 0, 0, 0.1768)

```

 

この時点で、長さが`|raw| = √(0.9268²+0.1768²) = √(0.8590+0.0313) = √0.8902 ≈ 0.9435`となり、**1ではない**。2点を球面上でそのまま直線(弦)で結んでいるため、球の内側を通ってしまい、長さが1未満に縮むのである。これは単位クォータニオンとして無効な値なので、実装では必ず正規化する。

 

```

Nlerp(0.25) = raw / 0.9435 = (0.9268/0.9435, 0, 0, 0.1768/0.9435) = (0.9823, 0, 0, 0.1874)

```

 

正規化はしたが、これを2-5節で求めた本物のSlerpの結果`Slerp(0.25) = (0.9808, 0, 0, 0.1951)`と比べると、**一致しない**(w成分で`0.9823 vs 0.9808`、z成分で`0.1874 vs 0.1951`という差が生じている)。もし正規化線形補間の角速度が本当に一定なら、Slerpと厳密に同じ値になるはずである(実際、2-5節で見た通り、両者は`t=0`・`t=0.5`・`t=1`では偶然一致する——対称性により中間点だけは一致するためである)。しかし`t=0.25`という非対称な点では値が食い違うことが、上の検算により確認できた。これは、正規化線形補間が球の内部を通る「弦」に沿って進むため、球面(弧)上を一定角速度で進む本来のSlerpに比べて、区間の前半・後半で進む角度にムラが生じることの、具体的な数値による証拡である。

 

### 2-7. ジンバルロックとの関係 — オイラー角の補間とクォータニオンSlerpの比較

 

→BOOK-0226第二章2-1節は、オイラー角(ロール・ピッチ・ヨー)による回転表現が、特定の姿勢でジンバルロックという自由度の縮退を起こすことを見た。この弱点は、単に「ある1つの姿勢」を表すときだけでなく、2つの姿勢の**あいだ**を補間するときに、いっそう深刻な形で現れる。

 

オイラー角を素朴に補間する(ロール・ピッチ・ヨーの3つの角度をそれぞれ独立に線形補間する)方式では、補間の途中経路が、たまたまジンバルロックの姿勢(ピッチ±90度)の近くを通過してしまうことがある。この場合、たとえ始点と終点がどちらも正常な姿勢であっても、補間の途中で自由度が一時的に縮退し、ロールとヨーの区別がつかなくなる区間が生じてしまう。これは、2つの角度をどんな順で組み合わせて回転させるかという表現方法そのものに起因する問題であり、角度の刻み方をどれだけ工夫しても、原理的には解消できない。

 

クォータニオンのSlerpは、この問題を構造的に回避する。Slerpは`(ロール,ピッチ,ヨー)`のような3つの独立した角度に分解してから補間するのではなく、4次元の単位球面上の1つの弧を直接たどる。回転を表現するのに「3つの角度の役割分担」という不安定な足場を経由しないため、途中経路がどこを通ろうと、自由度が縮退する特異点(ジンバルロック)にそもそも遭遇しようがない。→第一章のキャンディラップ問題が「位置を直接ブレンドする弊害」だったのに対し、ジンバルロックは「回転を3つの独立した角度に分解する弊害」であり、どちらも「本来1つのなめらかな量であるものを、素朴なやり方でバラバラに(あるいは直線的に)扱ってしまう」という共通の落とし穴から生じている。

 

### 深掘りコラム: 最短弧問題 — なぜ実装では内積の符号を先にチェックするのか

 

→BOOK-0226第二章の深掘りコラムは、あるクォータニオン`q`とその符号をすべて反転した`-q`が、まったく同じ回転を表すという**二重被覆**の性質を紹介していた。この性質は、Slerpの実装において、見過ごせない実務上の落とし穴を生む。

 

2-3節の導出は、`θ=arccos(q1・q2)`を、`q1`から`q2`までの(4次元球面上の)角距離とみなして式を組み立てた。しかし`q1・q2<0`のとき、`θ`は90度を超える鈍角になる。この場合、Slerpは`q1`から`q2`まで、大円上の**長い方の弧**をたどってしまう——`q2`と同じ回転を表す`-q2`のほうが、`q1`からずっと近い(角距離が小さい)にもかかわらず、である。

 

この対策として、実装では補間を始める前に必ず`q1・q2`の符号を確認し、負であれば`q2`(あるいは`q1`)の全成分の符号を反転させてから`Slerp`を計算する、という一手間を加える。二重被覆の性質により、符号を反転しても`q2`が表す実際の回転はまったく変わらないため、この操作は安全に行える。→BOOK-0226「実装のこつ集」その2が「クォータニオンの補間前には、内積の符号を確認する」と実務的な対処法だけを述べていたのに対し、本節はその対処が**なぜ**必要なのかを、2-3節の導出(`θ`を鈍角のまま使うと長い弧を選んでしまう)に基づいて説明した。

 

---

 

## 休憩所②: まとめ箱 — 第二章のポイント

 

```

Slerpの発想: 4次元の単位球面上の大円弧を、一定角速度で進む補間

導出: q(t)=q1cos(tθ)+q_perp・sin(tθ)を境界条件q(1)=q2で解き、加法定理sin(A-B)=sinAcosB-cosAsinBを使うと

Slerp(t) = [sin((1-t)θ)/sinθ]q1 + [sin(tθ)/sinθ]q2 が導かれる

 

検算1(恒等式): θ=45°,t=0.25で sinθcos(tθ)-cosθsin(tθ) = sin((1-t)θ) が両辺0.55557で一致

検算2(BOOK-0226の値を再利用): q1=(1,0,0,0),q2=(0.7071,0,0,0.7071)

Slerp(0.5)=(0.9239,0,0,0.3827)=45度回転と一致/Slerp(0.25)=(0.9808,0,0,0.1951)=22.5度回転と一致

 

検算3(速度の不均一性): raw lerp(0.25)の生の長さ0.9435(≠1)→正規化Nlerp(0.25)=(0.9823,0,0,0.1874)

真のSlerp(0.25)=(0.9808,0,0,0.1951)と不一致 → Nlerpの角速度は一定でないことが数値で確認できた

 

ジンバルロックとの関係: オイラー角補間は途中経路がジンバルロック姿勢を通過しうる/Slerpは4次元球面を直接たどるため原理的に回避

深掘り: q1・q2<0のとき長い弧を選んでしまう(二重被覆の落とし穴)→符号確認して反転するのが実務対処

```

 

---

 

## 第三章: 空間分割によるレイキャスト高速化(BVH) — 枝を分けて絞り込む

 

### 3-1. 問題設定: 物体が数万個あるとき、レイキャストはどう遅くなるか

 

→BOOK-0226第四章は、1本のレイと1つの平面・1つの球との交差判定の式を確立した。しかし、その深掘りコラムが述べていた通り、「物体の数が数千・数万に増えると、すべての物体に対して毎回この計算を行うのは非効率になる」。この**線形探索(せんけいたんさく、シーン内のすべての物体に対して、1つずつ順番に交差判定を行う方式)**は、物体数`n`に対して常に`n`回の交差判定を要する——計算量の言葉で言えば**O(n)(オーダーn、物体数に比例して計算量が増えることを表す記法)**である。

 

本章が扱う**BVH(びーぶいえいち、バウンディングボリューム階層、Bounding Volume Hierarchy、水準七: シーン内の物体を、箱状の領域〈バウンディングボリューム〉でグループ化し、木構造に整理しておくことで、レイと交差しうる物体をすばやく絞り込む空間分割の技法)**は、この計算量を**O(log n)(オーダー・ログn、物体数が倍になっても、計算量はわずかしか増えないことを表す記法)**にまで削減する。BOOK-0226第四章は、この技法の存在を名前だけ紹介して「本書の範囲を超える」としていた。本章ではその構築と走査を、具体的な数値とともに扱う。

 

### 3-2. AABB(軸並行境界箱)とは何か

 

BVHの各ノード(木構造の節)は、その配下にあるすべての物体を過不足なく包み込む、簡単な形の箱を持つ。最も広く使われるのが**AABB(えーえーびーびー、軸並行境界箱、Axis-Aligned Bounding Box、水準六: 座標軸(x・y・z)に辺が平行な、直方体の領域。物体を囲む最小・最大の座標だけで表現できる)**である。AABBは、各軸ごとの最小値`min`と最大値`max`という、わずか2つの点(3次元なら合計6つの数)だけで表現できる。

 

```

AABB = { min=(minX,minY,minZ), max=(maxX,maxY,maxZ) }

```

 

### 3-3. 検算: 2つのAABBを合成する

 

BVHを構築する過程では、複数の子のAABBから、それらすべてを包む親のAABBを求める操作を繰り返す。この**合成(和集合、union)**は、各成分ごとの最小値・最大値を取るだけでよい。

 

```

合成後のmin = 各成分ごとにmin(箱1のmin, 箱2のmin)

合成後のmax = 各成分ごとにmax(箱1のmax, 箱2のmax)

```

 

**検算**: →BOOK-0226第一章が使った一辺2の立方体(`min=(-1,-1,-1), max=(1,1,1)`)を箱Aとし、箱Bを`min=(0,0,2), max=(3,2,5)`とする。

 

```

合成min = (min(-1,0), min(-1,0), min(-1,2)) = (-1,-1,-1)

合成max = (max(1,3), max(1,2), max(1,5)) = (3,2,5)

```

 

この合成箱`min=(-1,-1,-1), max=(3,2,5)`が、本当に箱A・箱Bの両方を包んでいるかを確認する。箱Aの`max=(1,1,1)`は合成`max=(3,2,5)`の各成分以下(`1≤3,1≤2,1≤5`)、箱Bの`min=(0,0,2)`は合成`min=(-1,-1,-1)`の各成分以上(`0≥-1,0≥-1,2≥-1`)——両方とも条件を満たし、合成箱が正しく2つの箱を包含していることが検算できた。

 

### 3-4. レイ-AABB交差判定 — スラブ法

 

レイ`P(t)=O+tD`(→BOOK-0226第四章、`O`=始点、`D`=方向)がAABBと交差するかどうかは、**スラブ法(すらぶほう、slab method、水準七: x・y・z軸それぞれについて、レイがその軸方向の「薄い板〈スラブ〉」の範囲内にいる区間を求め、3つの区間すべての共通部分が存在するかどうかで交差を判定する手法)**によって効率よく判定できる。

 

各軸について、レイがその軸のスラブ(`min`〜`max`の範囲)に入る時刻`t`の区間を求める。

 

```

軸ごとに: t1 = (min - O) / D, t2 = (max - O) / D (D<0のときはt1,t2を入れ替えて、常にt1≤t2にする)

tenter = 全軸のmin(t1,t2)のうちの最大値

texit = 全軸のmax(t1,t2)のうちの最小値

 

tenter ≤ texit かつ texit ≥ 0 ならば交差する(区間[max(tenter,0), texit]が交差区間)

```

 

`D`のある成分がちょうど0(レイがその軸に垂直)の場合は特別扱いが必要で、始点の該当成分がスラブの範囲内にあればその軸は無制約(区間は`-∞〜+∞`)、範囲外なら永遠に交差しない(空の区間)。

 

### 3-5. 検算: スラブ法でヒット/ミスを判定する

 

3-3節と同じ立方体(`min=(-1,-1,-1), max=(1,1,1)`)に対し、2本のレイを試す。

 

**ヒットする例**: `O=(-3,0,0)`, `D=(1,0,0)`(x軸方向の単位ベクトル、立方体の中心の高さ・奥行きをまっすぐ貫く)。

 

```

x軸: t1=(-1-(-3))/1=2, t2=(1-(-3))/1=4 → [2,4]

y軸: D_y=0, O_y=0は[-1,1]の範囲内 → 無制約([-∞,+∞])

z軸: D_z=0, O_z=0は[-1,1]の範囲内 → 無制約([-∞,+∞])

 

tenter = max(2,-∞,-∞) = 2

texit = min(4,+∞,+∞) = 4

```

 

`tenter(2) ≤ texit(4)`かつ`texit≥0`なので交差する。交点を検算すると、`P(2)=(-3+2,0,0)=(-1,0,0)`(`x=-1`の面上、入射点)、`P(4)=(-3+4,0,0)=(1,0,0)`(`x=1`の面上、出射点)——どちらもちょうど立方体の面上にあり、正しく検算できた。

 

**ミスする例**: `O=(-3,5,0)`, `D=(1,0,0)`(同じ方向だが、`y=5`という、立方体の`y`の範囲`[-1,1]`から大きく外れた高さを通る)。

 

```

x軸: t1=2, t2=4 → [2,4](変化なし)

y軸: D_y=0, O_y=5は[-1,1]の範囲外 → 空の区間(この軸だけで交差なしが確定)

```

 

y軸の判定だけで、この立方体とは決して交差しないことが分かる(`y=5`の高さを通る水平なレイが、`y`の範囲が`[-1,1]`までしかない立方体に当たるはずがない、という直感とも一致する)。

 

### 3-6. BVHの構築 — 木構造への分割

 

BVHは、シーン内の物体を、次のような**上から下へ(トップダウン)**の手順で木構造に組み上げる。

 

1. 現在のノードが担当する物体すべてのAABBを合成し(3-3節)、そのノードのバウンディングボリュームとする。

2. 物体数が少なければ(実装ではしばしば数個程度を目安に)、それ以上分割せず**葉ノード**として物体をそのまま格納する。

3. そうでなければ、物体群を2つのグループに分割する分割軸(多くの場合、現在のAABBの一番長い辺の軸)と分割位置(物体の中心の中央値など)を決め、それぞれのグループに対して1・2を再帰的に繰り返す。

 

**検算**: 4つの物体を`x`軸上に配置する。

 

```

物体A: min=(0,0,0), max=(1,1,1) (中心x=0.5)

物体B: min=(2,0,0), max=(3,1,1) (中心x=2.5)

物体C: min=(10,0,0), max=(11,1,1) (中心x=10.5)

物体D: min=(12,0,0), max=(13,1,1) (中心x=12.5)

```

 

ルートのAABBは4つすべてを合成して`min=(0,0,0), max=(13,1,1)`。最も長い辺は`x`軸(長さ13、`y`・`z`はどちらも長さ1)なので`x`軸で分割する。中心`x`座標で並べると`0.5, 2.5, 10.5, 12.5`となり、明確な間隔(`2.5`と`10.5`のあいだに大きな空白)があるので、中央で`{A,B}`と`{C,D}`の2グループに分ける。

 

```

左の子(A,Bを合成): min=(0,0,0), max=(3,1,1)

右の子(C,Dを合成): min=(10,0,0), max=(13,1,1)

```

 

どちらの合成も3-3節の式(成分ごとのmin/max)通りであり、ルート→2つの子→4つの葉、という3段の木構造が組み上がる。

 

### 3-7. BVHの走査 — 枝刈りによる高速化

 

BVHの真価は、レイキャストの際に発揮される。ある物体のAABBとレイが交差しなければ、その内側にあるどの物体ともレイは絶対に交差しない(バウンディングボリュームは中身をすべて包含しているため)。この事実により、レイがあるノードのAABBと交差しなければ、そのノード配下の**すべての物体を1つずつ調べることなく、部分木ごと丸ごと除外**できる。これを**枝刈り(えだかり、pruning)**と呼ぶ。

 

**検算**: 3-6節のBVH(ルート・左の子`{A,B}`・右の子`{C,D}`)に対し、レイ`O=(-1,0.5,0.5)`, `D=(1,0,0)`を、探索範囲`t∈[0, 5]`(たとえば近くの光源までの遮蔽を調べる、といった限られた距離だけを見たい場合を想定)で走査する。

 

```

ルートのAABB min=(0,0,0),max=(13,1,1): x軸t1=(0-(-1))/1=1, t2=(13-(-1))/1=14 → [1,14](y,z軸は無制約)

→ tenter=1, texit=14。探索範囲[0,5]と重なる([1,5]の部分がある)ので、子を調べる。

 

左の子 min=(0,0,0),max=(3,1,1): x軸t1=1, t2=4 → [1,4]

→ tenter=1, texit=4。探索範囲[0,5]と重なるので、この中の物体(A,B)を個別に調べる。

 

右の子 min=(10,0,0),max=(13,1,1): x軸t1=(10-(-1))/1=11, t2=(13-(-1))/1=14 → [11,14]

→ tenter=11。探索範囲の上限t=5より手前にすら到達しない(11>5)ので、この枝は丸ごと除外できる。

```

 

このレイは幾何学的には(探索範囲を無限に取れば)左右どちらの箱とも交差するが、探索範囲を`t∈[0,5]`に限定した場合、右の子は`tenter=11`の時点で範囲外と分かるため、その配下にある物体CとDを個別にテストする必要が一切ない。線形探索であれば4つの物体すべてを調べていたところ、BVHでは物体CとDのテストを、まるごと省略できたことになる。

 

なお、この4物体だけの小さな例では、ルート・左・右という3回の箱テストのあとに、なおA・Bの2回の物体テストが必要であり、合計5回の判定が発生する(線形探索の4回より、むしろ多い)。BVHの箱テスト自体にもコストがかかるため、物体数が少ないうちは、木構造のオーバーヘッドが線形探索の手軽さを上回れないことがある——この点は次節の計算量比較とあわせて、正直に押さえておくべき注意点である。

 

### 3-8. 検算: 線形探索とBVH探索の計算量比較

 

BVHの効果が本当に発揮されるのは、物体数`n`が大きくなったときである。木がおおむね均等に分岐している(**平衡**している)と仮定すると、ルートから葉までの深さはおよそ`log₂(n)`(2進の対数、`n`を2で何回割ったら1になるかを表す数)であり、各階層で高々数回の箱テストを行うだけで、目的の葉(あるいは「交差なし」という結論)にたどり着ける。線形探索の計算量が`O(n)`であるのに対し、平衡なBVHの探索は`O(log n)`——物体数が増えても、計算量の増え方がはるかに緩やかになる。

 

具体的な物体数で比較する。

 

```

物体数n 線形探索(O(n)) の判定回数 BVH(O(log n)、⌈log₂n⌉) の目安判定回数

10 10 4 (log₂10 ≈ 3.32)

100 100 7 (log₂100 ≈ 6.64)

1,000 1,000 10 (log₂1000 ≈ 9.97)

10,000 10,000 14 (log₂10000 ≈ 13.29)

100,000 100,000 17 (log₂100000 ≈ 16.61)

1,000,000 1,000,000 20 (log₂1000000 ≈ 19.93)

```

 

物体数が100万に達すると、線形探索は最悪100万回の交差判定を要するのに対し、平衡なBVHはわずか約20回の箱テストで済む——比にしておよそ5万分の1(`1,000,000 / 20 = 50,000`)である。ただし、これは木が均等に分岐している理想的な場合の見積もりであり、分割の質が悪い(偏った)BVHでは、最悪の場合`O(n)`に近い性能まで劣化しうることも、誠実に付け加えておく必要がある。この「分割の質」を扱うのが、次の深掘りコラムである。

 

### 深掘りコラム: BVHの「質」— 分割方法とSAH(表面積ヒューリスティック)

 

3-6節の検算では、物体の中心座標をそのまま中央値で2分する、**中央値分割**という素朴な方法を使った。この検算例では4つの物体が自然に2つの塊に分かれていたため、中央値分割でも十分に良いBVHが得られた。しかし、実際のシーンでは、物体の分布はもっと不規則であり、どの軸で・どこで分割するかによって、できあがるBVHの「質」(=レイキャストが実際にどれだけ速くなるか)は大きく変わる。

 

この「質」を数値で評価するための代表的な指標が**SAH(えすえーえいち、表面積ヒューリスティック、Surface Area Heuristic、水準八: 候補となる分割方法それぞれについて、期待されるレイ交差判定コストを、分割後の各領域の表面積と物体数から見積もり、そのコストが最小になる分割を選ぶための評価基準)**である。直感的には、「表面積が大きい箱ほど、ランダムなレイがその箱に当たる確率も高い」という考え方に基づき、`(左の子の表面積×左の物体数) + (右の子の表面積×右の物体数)`のような値を複数の分割候補について見積もり、この値が最小になる分割を採用する。3-6節の中央値分割は実装が単純で高速だが、SAHはより計算コストをかけて、レイキャスト時の実際の性能により近い、質の高い分割を選び出す。多くの実務向けBVH実装は、構築時の計算コストと、走査時の速度向上との、この種のトレードオフの上に成り立っている。

 

---

 

## 休憩所③: まとめ箱 — 第三章のポイント

 

```

問題: 物体数nに比例するO(n)の線形探索(BOOK-0226第四章のレイ-平面/レイ-球判定を、n個すべてに対して行う非効率)

 

AABB合成: 成分ごとのmin/max。検算: 箱A(-1,-1,-1)-(1,1,1)、箱B(0,0,2)-(3,2,5)→合成(-1,-1,-1)-(3,2,5)、包含を確認

 

スラブ法: 各軸の区間の共通部分で交差判定。検算: O=(-3,0,0),D=(1,0,0)→[2,4]でヒット(面上と一致)

O=(-3,5,0)は y軸の時点でミス(y=5が範囲[-1,1]外)

 

BVH構築: AABBを合成しながらトップダウンに分割。検算: 4物体(x=0.5,2.5,10.5,12.5)→左{A,B}右{C,D}の2分木

BVH走査: 交差しない枝は配下ごと除外(枝刈り)。検算: tmax=5の探索で右の枝(tenter=11)を物体テストなしに除外

 

計算量比較: n=100万で線形探索100万回 vs BVH約20回(約5万分の1)。ただし小規模(n=4)ではBVHの箱テスト自体のコストが線形探索を上回りうる

深掘り: SAH(表面積ヒューリスティック)は表面積×物体数でコストを見積もり、分割の質を数値で最適化する

```

 

---

 

## 実装のこつ集 — 現場で迷ったときの判断材料

 

→BOOK-0226の「実装のこつ集」に倣い、本書の内容を実務に落とし込む際に迷いやすい点を4つ、判断材料として収録する(正式な技-ID採番は司令塔側の台帳管理に委ねるため、本書ではあえて技-番号を付さない)。

 

**その1: 不自然な変形(キャンディラップ)を疑ったら、まず重みの合計とバインド逆行列を確認する**

 

適用条件: 関節を大きく曲げたときに、皮膚が不自然に痩せ細る、あるいは突き刺さるような変形になる。

目安範囲: →第一章1-4節のLBS式で、各頂点の重み`wᵢ`の合計が本当に1になっているかをまず確認する(合計が1からずれていると、頂点が伸び縮みする別種のバグが混入する)。重みの合計が正しいのに痩せ細りが起きる場合は、それは実装のバグではなく、→第一章1-6節で検算したLBS自体の構造的な弱点(キャンディラップ問題)である可能性が高く、この場合はデュアルクォータニオンスキニングなど別の手法への切り替えを検討する判断材料になる。

 

**その2: Slerpのゼロ割りに注意する(θが0に近いとき)**

 

適用条件: 2つの姿勢がほとんど同じ(あるいは完全に同じ)ときにSlerpを計算すると、実装によっては例外やNaN(非数)が発生する。

目安範囲: →第二章2-3節の式は分母に`sinθ`を持つため、`θ`が0に非常に近い(`q1`と`q2`がほとんど同じ姿勢)とき、`sinθ`も0に近づき、数値的に不安定になる。実務上は、`θ`が十分小さい場合には、Slerpの代わりに素朴な線形補間(→第二章2-6節のNlerp)で近似しても、視覚的な差はほとんど生じない。多くの実装は、`θ`がある閾値より小さいときだけNlerpに切り替える、という条件分岐を持つ。

 

**その3: BVHは物体数が少ないときはオーバーヘッドが線形探索を上回りうる**

 

適用条件: BVHを導入したのに、想定したほど速くならない、あるいはむしろ遅くなった。

目安範囲: →第三章3-7節の検算(物体数4個)で見た通り、BVHの箱テスト自体にもコストがかかるため、物体数が少ない場面(シーン内の物体が数個〜十数個程度)では、木構造の構築・走査のオーバーヘッドが、単純な線形探索の手軽さを上回れないことがある。BVH導入の効果は、→第三章3-8節の比較表が示す通り、物体数が数百・数千以上に達してはじめて顕著になる。

 

**その4: 動く物体を含むシーンでは、BVHの再構築コストにも目を配る**

 

適用条件: シーン内の物体が毎フレーム移動・変形するとき、BVHをどう更新すべきか迷う。

目安範囲: →第三章3-6節の構築手順を毎フレーム最初からやり直すのは、多くの場合コストが高すぎる。実務では、木の形(どの物体がどの枝に属するか)は維持したまま、各ノードのAABBだけを子の現在位置に合わせて更新し直す**リフィット(refit、木構造を再構築せず、バウンディングボリュームだけを子から親へ再計算し直す軽量な更新手法)**という手法がよく使われる。ただし物体が大きく動き回ると、リフィットだけでは木の形自体が実情に合わなくなり(過度に大きく重なり合った箱ばかりになり)、定期的な完全再構築が必要になる場合もある。

 

---

 

## 終章 — 3つの保留に決着をつけて

 

本書は、→BOOK-0226が名前の紹介にとどめていた3つの技術に、検算つきで決着をつけてきた。第一章では、BOOK-0226第三章の「行列の合成`M=R×S`」を、ボーンの数だけ連鎖する一般的な階層構造へと広げ、リニアブレンドスキニングの数式を確立し、その古典的な弱点であるキャンディラップ問題を、90度・180度という2つの具体的な角度で、関節からの距離が`1→0.7071→0`へと縮んでいく様子まで検算した。そのうえで、BOOK-0226終章が「現役の実装課題」と名指ししていたデュアルクォータニオンスキニングの仕組みの概要にも触れ、平行移動のエンコード・デコードが正確に一致することを確認した。

 

第二章では、BOOK-0226第二章2-7節が名前だけ紹介していたSlerpの式を、単位球面上の等角速度補間という幾何学的な発想から、加法定理を使って自分の手で導出した。BOOK-0226自身の検算例(90度回転を表すクォータニオン)を再利用し、`t=0.5`・`t=0.25`のSlerpがどちらも「同軸の回転を単純に角度補間した結果」と厳密に一致することを確かめ、さらに素朴な線形補間(Nlerp)がSlerpと`t=0.25`で食い違うことを示して、「速度が不均一になる」という現象を、具体的な数値の不一致として裏付けた。

 

第三章では、BOOK-0226第四章のレイ-平面・レイ-球交差判定の先に、物体数が数万に達したときの高速化技法であるBVHを、AABBの合成・スラブ法によるレイ-AABB交差判定・木構造の構築と枝刈りによる走査という4つの側面から、具体的な数値とともに扱った。物体数100万でおよそ5万分の1に判定回数が減る一方、物体数が少ないうちはBVHのオーバーヘッドが線形探索を上回りうるという、教科書が省略しがちな注意点も、小さな検算例によって誠実に示した。

 

### 誠実な位置づけの再確認

 

本書の冒頭で述べた通り、本書はCLAUDE.md「ギャップ駆動辞書拡充規約」に基づく新規GAP番号の解消を目的とした書籍ではない。本書が埋めたのは、正式なギャップ台帳上の穴ではなく、→BOOK-0226自身が終章で「現役の実装課題」「所見」として名指ししながら、本文では扱いきれなかった3つの具体的な保留——スキニング・Slerpの導出・BVH——である。この位置づけの違いを、ここに改めて明記しておく。またBOOK-0226と同様、FUNC辞書(コード生成カード側)に骨格アニメーション・空間分割データ構造に対応するカードが存在するかどうかは、本書の関知するところではなく、gakumon(理論・書籍側)の範囲にとどまることも、あわせて明記しておく。

 

### 5冊の関係地図

 

```

BOOK-0071(線形代数・水準一〜四) BOOK-0187(射影数学・水準四〜八)

ベクトル・行列・行列式・固有値の入口 カメラ→スクリーン(片道)

│ │

▼ ▼

BOOK-0120(線形代数・水準五〜六) BOOK-0226(3DCG実装数学・第1巻・水準五〜八)

対角化・スペクトル定理・P⁻¹が初登場 外積・クォータニオン・逆行列と法線変換・

│ レイキャスト(逆方向)・ジオメトリ生成

└──────────────┬──────────────────────┘

▼

BOOK-0227 本書(水準六〜八)

骨格アニメーション(第一章、BOOK-0226第三章の行列合成を一般化)・

Slerpの導出(第二章、BOOK-0226第二章のクォータニオンを土台に)・

BVH(第三章、BOOK-0226第四章のレイ交差判定に空間分割を追加)

```

 

BOOK-0226が「道具箱をそろえる旅」だったとすれば、本書は「その道具箱を実際に使い、動かし、たくさんの物体の中から絞り込む旅」だった。骨を曲げ、弧を描き、枝を分ける——3つの動詞のすべてが、前巻の道具立てのうえに、具体的な数値の検算とともに積み上がったことを、本書はここに記録しておく。

 

---

 

## 章末: 簡易階段図(骨格アニメーション・Slerp・BVHを積み上げる階段)

 

```

[水準六] 骨格アニメーション: ボーン階層の行列連鎖(BOOK-0226 M=R×Sの一般化)

検算: 肩を90度回転→肘(0,2)・手首(0,4)、バインドポーズの回転結果と一致

▲

│ 「親のグローバル変換×自分のローカル変換」という連鎖のルール

[水準六] リニアブレンドスキニング(LBS): 重み付き合成 v'=Σwᵢ(Mᵢ・Bᵢ⁻¹・v)

検算: 90度肘曲げでv=(2,1)→(1.5,0.5)、関節距離1→0.7071

▲

│ 複数のボーンから頂点への影響を、重みで足し合わせる

[水準六] キャンディラップ問題: LBSの古典的弱点、距離=r・cos(φ/2)

検算: 180度で関節距離が0へ完全崩壊/深掘り: デュアルクォータニオン(8成分・水準八)で緩和

▲

│ 位置を直接ブレンドすることの構造的な弱点

[水準七] Slerpの導出: 単位球面上の等角速度補間 → 加法定理で式を導出

検算: BOOK-0226の90度回転クォータニオンを再利用、t=0.5・t=0.25で角度補間と一致

▲

│ 「一定角速度で球面を進む」という要請から式が自然に出る

[水準七] なぜ素朴な線形補間では速度が不均一か: raw lerpは長さ1未満→正規化してもSlerpとt=0.25で不一致

▲

│ 弦(直線)と弧(球面上の道)の違い

[水準七] BVH: AABB合成・スラブ法によるレイ-AABB判定・木構造の構築と枝刈り

検算: n=100万で線形探索100万回 vs BVH約20回(約5万分の1)

│

└── 3つの技術すべてが、BOOK-0226の道具(行列合成・クォータニオン・レイ交差判定)の上に積み上がる

 

横の広がり:

[水準六] LBS(位置を直接ブレンド) ←(対比)→ デュアルクォータニオンスキニング(変換そのものをブレンド)

[水準七] Slerp(球面上の弧、一定角速度) ←(対比)→ Nlerp(球面内部の弦、速度不均一)

[水準七] 線形探索(O(n)、総当たり) ←(対比)→ BVH探索(O(log n)、枝刈りで絞り込む)

 

現在のフロンティア(第一章・第三章):

デュアルクォータニオンスキニングの完全なブレンド式(正規化を含む)、およびSAHによるBVH構築の

最適化は、いずれも本書では概要の紹介にとどまっており、GPU上での実装(コンピュートシェーダに

よるボーン変形、ハードウェアレイトレーシングとBVHの関係)とあわせて、現役の実装課題として

残されている。

 

次の冊子への矢印:

本書の続巻を正式に予告することは避ける(→BOOK-0226終章の判断・GAKUMON_UNIVERSE.md終章の

階段図規約に倣う)。ただし本書が閉じた地点から自然に続きうる候補として、デュアルクォータニオン

スキニングの完全なブレンド式の導出、SAHによるBVH構築の最適化、GPU上でのボーン変形実装

(コンピュートシェーダ)などが考えられる、という所見のみを残す。

```

 

---

 

## 参照文献(公的資料・専門機関・教科書的資料)

 

1. Magnenat-Thalmann, N., Laperrière, R., Thalmann, D., "Joint-Dependent Local Deformations for Hand Animation and Object Grasping," Proceedings of Graphics Interface, 1988 — 頂点をボーンに結び付けて変形させる、スキニングの初期的手法に関する原論文。

2. Lewis, J.P., Cordner, M., Fong, N., "Pose Space Deformation: A Unified Approach to Shape Interpolation and Skeleton-Driven Deformation," ACM SIGGRAPH 2000 — 線形ブレンドスキニングの構造的な弱点に関する議論を含む論文。

3. Kavan, L., Collins, S., Žára, J., O'Sullivan, C., "Skinning with Dual Quaternions," Proceedings of ACM SIGGRAPH Symposium on Interactive 3D Graphics and Games (I3D), 2007 — デュアルクォータニオンスキニングの提案論文。キャンディラップ問題の議論と解決策を含む。

4. Clifford, W. K., "Preliminary Sketch of Biquaternions," Proceedings of the London Mathematical Society, 1873 — 二重数・デュアルクォータニオンの数学的原典。

5. O'Connor, J.J. and Robertson, E.F., "William Kingdon Clifford," MacTutor History of Mathematics Archive, University of St Andrews — クリフォードの生涯と業績に関する数学史資料。

6. Weisstein, Eric W., "Dual Number," MathWorld — 二重数の定義に関する数学参考資料。

7. Shoemake, Ken, "Animating Rotation with Quaternion Curves," ACM SIGGRAPH Computer Graphics, 1985 — 球面線形補間(Slerp)の原論文(BOOK-0226に続き再掲)。

8. Dunn, F. and Parberry, I., *3D Math Primer for Graphics and Game Development* — クォータニオン・Slerpの導出を扱うゲーム開発向け数学教科書(BOOK-0226に続き再掲)。

9. Lengyel, Eric, *Mathematics for 3D Game Programming and Computer Graphics* — Slerpの幾何学的導出、スキニングの数学的基礎を扱う教科書(BOOK-0226に続き再掲)。

10. Rubin, Steven M. and Whitted, Turner, "A 3-Dimensional Representation for Fast Rendering of Complex Scenes," ACM SIGGRAPH Computer Graphics, 1980 — バウンディングボリューム階層による高速化の初期的提案論文。

11. Ericson, Christer, *Real-Time Collision Detection* — AABB・スラブ法・BVHの構築と走査を扱う代表的教科書(BOOK-0226に続き再掲)。

12. Akenine-Möller, T., Haines, E., Hoffman, N., *Real-Time Rendering* — スキニング・Slerp・BVHのすべてを扱うリアルタイムCG分野の代表的教科書(BOOK-0226に続き再掲)。

13. Gregory, Jason, *Game Engine Architecture* — 骨格アニメーションシステム・空間分割構造の実装を、ゲームエンジン設計の観点から扱う教科書。

14. Scratchapixel, "Bounding Volume Hierarchy (BVH) — Introduction to Acceleration Structures" — BVHの構築と走査に関する公開技術解説資料(BOOK-0226のScratchapixel項目に続く関連ページ)。

 




# BOOK-0227 情報派生_3DCG幾何学の実装数学 — 曲がる骨、巡る弧、分かれる枝(第2巻)
  1. 目次
  2. 小説情報
  3. 縦書き
  4. しおりを挟む
  5. お気に入り登録
  6. 評価
  7. 感想
  8. ここすき
  9. 誤字
  10. 閲覧設定