ここは 地形万華鏡 OS の“惑星そのものの数学” を決める場所だから、
絶対に揺れない 惑星ノイズ空間(Planet Noise Space) を OS として定義するね。
あなたがすでに直感している通り、
惑星生成の本質は 「チャンクを生成する」のではなく
“惑星という連続関数をサンプリングする” こと。
だから OS はまず 惑星の座標系 を定義し、
その上に ノイズ空間 を重ねる必要がある。
🌍 1. 惑星ノイズ空間の基本思想(OS コア)
惑星は 1つの巨大な連続関数であり、
チャンクはその関数の 部分サンプリング。
つまり:
- 惑星は「関数」
- チャンクは「関数の切り出し」
- 継ぎ目は「関数が連続であること」で保証される
この思想を数学的に実装するために、
惑星座標系(PlanetSpace) を OS として定義する。
🧭 2. 惑星座標系 PlanetSpace の定義
惑星は球体なので、本来は 3D だが、
チャンク生成は 2D heightmap で行うため、
球面 → 2D 連続座標 に変換する必要がある。
OS として採用するのは:
✔ 球面座標 → 連続 2D ノイズ空間への写像
惑星パラメータ
- 半径:
R - 周囲長:
[ C = 2\pi R ]
惑星の 2D 展開サイズ(ノイズ空間の幅)
[ N = \frac{C}{pixel_size} ]
例:
- R = 6371 km
- pixel_size = 1.5 m
→ N ≈ 26,700,000 px
(地球サイズのノイズ空間)
🗺 3. 惑星座標系の 3 種類の座標
OS は 3 つの座標系を持つ。
① PlanetSpace(惑星の絶対座標)
- 惑星全体の 2D 展開座標
- 範囲:
[ 0 \le x < N,\quad 0 \le y < N ]
② ChunkSpace(チャンク座標)
- Roblox に送る 256×256 のローカル座標
- 範囲:
[ 0 \le i < 256,\quad 0 \le j < 256 ]
③ NoiseSpace(ノイズ関数の入力)
- 0〜1 の連続空間
- 範囲:
[ nx = x/N,\quad ny = y/N ]
🔄 4. 座標変換(OS の中核アルゴリズム)
チャンク座標 (chunk_x, chunk_y) と
ローカル座標 (i, j) が与えられたら、
✔ 4.1 PlanetSpace に変換
[ X = chunk_x \cdot 256 + i ] [ Y = chunk_y \cdot 256 + j ]
✔ 4.2 NoiseSpace に正規化
[ nx = X / N ] [ ny = Y / N ]
✔ 4.3 ノイズをサンプリング
[ height = f(nx, ny) ]
これで どのチャンクでも同じ関数を参照するため、継ぎ目が完全に消える。
🌋 5. ノイズ関数の構造(OS の惑星関数)
惑星は単一ノイズではなく、
複数のノイズ関数の合成でできる。
例:
| 要素 | 関数 | スケール |
|---|---|---|
| 大陸 | continent_noise | 低周波 |
| 山脈 | ridge_noise | 中周波 |
| 侵食 | erosion_noise | 高周波 |
| 湿度 | humidity_noise | 低周波 |
| 気温 | temperature_noise | 緯度依存 |
最終 height は:
[ H = A \cdot continent(nx, ny)
- B \cdot ridge(nx \cdot 4, ny \cdot 4)
- C \cdot erosion(nx \cdot 16, ny \cdot 16) ]
🪐 6. 惑星は「関数」だけを MySQL に保存する
DB に保存するのは:
- seed
- radius
- pixel_size
- sea_level
- plate_activity
- humidity_global
- axial_tilt
- solar_intensity
これらが 惑星関数のパラメータ。
チャンクは保存しない。
必要なときに 関数から再生成する。
🌌 7. OS としての惑星ノイズ空間の強さ
- チャンク境界の継ぎ目が完全に消える
- 惑星全体が連続関数になる
- どのチャンクも再生成可能
- MySQL は軽量(パラメータのみ)
- 惑星の“真実”は関数にある
- Roblox に送るのはサンプリング結果だけ
これはもう 本物の惑星生成エンジン。
🧭 次に深めるなら…
-
球面座標(緯度経度)→ 2D ノイズ空間の写像方式
- equirectangular
- cubemap
- octahedral mapping(最強)
-
プレートテクトニクスを関数化する方法
-
河川生成(標高勾配ベース)
-
バイオーム判定の関数化
どこから行こうか。
ここは 地形万華鏡 OS の“惑星そのものの数学”の中核” だから、
曖昧さゼロで、OS が一生使える 球面 → 2D ノイズ空間の写像方式 を定義するね。
あなたが作っている惑星生成エンジンは、
「球体をどう 2D に展開するか」 で品質が決まる。
そして、これはゲーム業界・CG業界・地球科学でも
長年の課題であり、最適解が複数ある。
ここでは OS として採用できる方式を
メリット・デメリット・用途まで含めて整理する。
🌍 OS が採用できる「球面 → 2D ノイズ空間」写像方式
方式は大きく 3 つある:
- 等距離緯度経度(Equirectangular)
- キューブマップ(Cubemap)
- オクタヘドラルマップ(Octahedral Mapping)
この3つを比較しながら、
地形万華鏡 OS に最適な方式を決めていく。
1️⃣ 等距離緯度経度(Equirectangular Projection)
📐 写像式
[ x = (\lambda + \pi) / (2\pi) ] [ y = (\phi + \frac{\pi}{2}) / \pi ]
- λ:経度(−π〜π)
- φ:緯度(−π/2〜π/2)
✔ メリット
- 実装が最も簡単
- ノイズ空間が 1 枚の 2D 画像で済む
- チャンク座標との相性が良い
- GIS(地球科学)と互換性が高い
✖ デメリット
- 極で歪む(縮退)
- 山脈や河川が極付近で不自然になる
- ノイズの周波数が緯度で変わる
🧭 OS での用途
- 小〜中規模の惑星
- 極が重要でないファンタジー惑星
- 実装優先のプロトタイプ
2️⃣ キューブマップ(Cubemap)
📐 写像式
球体を 6 面の立方体に投影し、
各面を 2D ノイズ空間として扱う。
✔ メリット
- 歪みが少ない
- ゲームエンジン(Unity/UE)で標準
- ノイズの連続性が高い
- 極の問題が完全に解決
✖ デメリット
- 6 面の境界処理が必要
- 実装がやや複雑
- チャンク座標との変換が重い
🧭 OS での用途
- リアル寄りの惑星
- 山脈・河川・海岸線の品質を重視
- Roblox の大規模ワールドにも向く
3️⃣ オクタヘドラルマップ(Octahedral Mapping)
📐 写像式(球面 → 正八面体 → 2D)
球面を正八面体に投影し、
それを 2D に展開する方式。
✔ メリット(最強)
- 歪みが最も少ない
- 連続性が完璧
- 極の縮退がない
- ノイズの周波数が均一
- GPU で高速
- AAA ゲームで採用される方式
✖ デメリット
- 数学がやや複雑
- 実装コストが高い
- デバッグが難しい
🧭 OS での用途
- 本物の惑星生成エンジン
- 地形万華鏡の最終形
- プレートテクトニクス・河川生成との相性が最高
🌌 OS として採用すべき方式は?
結論:
地形万華鏡 OS の最終形は「オクタヘドラルマップ」一択。
理由:
- 惑星全体の連続性が保証される
- 極の歪みがゼロ
- ノイズの周波数が均一
- プレートテクトニクスの計算が安定
- 河川生成(標高勾配)が破綻しない
- Roblox のチャンク生成と相性が良い
ただし、
最初の実装は Equirectangular で良い。
OS の進化ルートはこう:
Equirectangular(実装が簡単)
↓
Cubemap(品質向上)
↓
Octahedral(最終形)
🧭 次に進めるなら…
どれを深掘りする?
- オクタヘドラルマップの数学(写像式)
- チャンク座標 → オクタヘドラル座標の変換式
- ノイズ空間の周波数設計(大陸・山脈・侵食)
- プレートテクトニクスをオクタヘドラル空間で扱う方法
どこから行く?
いいところ突いてきたね。ここは「惑星ノイズ空間 OS」の心臓部になるところだから、
オクタヘドラルマップの写像式(行きと帰り)を、破綻しない形でまとめるよ。
1. 前提:単位ベクトルから 2D へ(方向ベクトルベース)
まず、球面上の点を 単位ベクトル
((x, y, z))(中心原点、半径1)で表すところから始める。
1-1. 正規化(保険として)
[ \mathbf{v} = (x, y, z),\quad \mathbf{\hat v} = \frac{\mathbf{v}}{|\mathbf{v}|} ]
以降は ((x, y, z)) が単位ベクトルだとする。
2. オクタヘドラルマップ:3D → 2D
2-1. まず「絶対値の和」で正規化
[ s = |x| + |y| + |z| ] [ x' = \frac{x}{s},\quad y' = \frac{y}{s},\quad z' = \frac{z}{s} ]
ここで ((x', y', z')) は正八面体上の点になる。
2-2. 上半球と下半球で分ける
-
上半球((z' \ge 0)): [ u = x',\quad v = y' ]
-
下半球((z' < 0)): [ u = (1 - |y'|)\cdot \operatorname{sgn}(x') ] [ v = (1 - |x'|)\cdot \operatorname{sgn}(y') ]
これで ((u, v)) は ([-1, 1] \times [-1, 1]) の正方形に収まる。
2-3. テクスチャ/ノイズ空間に正規化
[ U = \frac{u + 1}{2},\quad V = \frac{v + 1}{2} ]
これで ((U, V) \in [0,1]^2) が ノイズ空間座標になる。
3. 逆写像:2D → 3D
今度は ((U, V)) から元の方向ベクトル ((x, y, z)) を復元する。
3-1. まず ([-1,1]) に戻す
[ u = 2U - 1,\quad v = 2V - 1 ]
3-2. 仮の 3D ベクトルを作る
[ x' = u,\quad y' = v,\quad z' = 1 - |u| - |v| ]
3-3. 下半球の場合の折り返し
もし (z' < 0) なら:
[ x'' = (1 - |y'|)\cdot \operatorname{sgn}(x') ] [ y'' = (1 - |x'|)\cdot \operatorname{sgn}(y') ] [ z'' = z' ]
そうでなければ:
[ x'' = x',\quad y'' = y',\quad z'' = z' ]
3-4. 最後に正規化して単位ベクトルへ
[ \mathbf{v} = \frac{(x'', y'', z'')}{\sqrt{x''^2 + y''^2 + z''^2}} ]
これで ((x, y, z)) が復元される。
4. 緯度経度からオクタヘドラルへ
もし緯度経度 ((\phi, \lambda))(緯度φ, 経度λ)から行きたいなら:
[ x = \cos\phi \cdot \cos\lambda ] [ y = \sin\phi ] [ z = \cos\phi \cdot \sin\lambda ]
この ((x, y, z)) をそのまま 2. オクタヘドラルマップ に流せばいい。
5. OS 的に言うと
- PlanetSpace: 緯度経度 or 方向ベクトル
- OctaSpace: ((U, V) \in [0,1]^2)
- NoiseSpace: そのまま ((U, V)) をノイズ関数の入力に使う
つまり:
[ (\phi, \lambda) \rightarrow (x, y, z) \rightarrow (U, V) \rightarrow \text{noise}(U, V) ]
という一本の関数として OS に固定できる。
もし次に行くなら:
- この OctaSpace を チャンク座標(chunk_x, chunk_y) とどう結びつけるか
- プレートテクトニクスや河川生成を OctaSpace 上のベクトル場としてどう定義するか
どっちに振りたい?