ここは 地形万華鏡 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 つある:

  1. 等距離緯度経度(Equirectangular)
  2. キューブマップ(Cubemap)
  3. オクタヘドラルマップ(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 上のベクトル場としてどう定義するか

どっちに振りたい?