🌏

第1回 Minecraft × PLY点群:3DGS PLY形式の応用を探る

に公開

📌 3D Gaussian Splatting(3DGS)と PLY形式

3D Gaussian Splatting とは

3D Gaussian Splatting(3DGS)は、NeRF(Neural Radiance Fields)系の最新3D再構成手法で、点群にガウス分布を持たせて高速レンダリングを行います。
従来のNeRFに比べ、圧倒的に高速でリアルタイム描画が可能です。
原理としては、シーンを 「色付きの半透明なガウス点」 で構成し、それらをGPU上で効率的に描画します。


出力形式としての PLY

3DGSの出力フォーマットとしてよく使われるのが PLY(Polygon File Format) です。
PLYはもともとスタンフォード大学で3Dスキャンデータを扱うために開発されたシンプルな形式で、点群やポリゴンメッシュを格納できます。

各点(頂点)には以下のような属性を付与できます。

  • 位置座標(x, y, z)
  • 色(r, g, b)
  • 法線ベクトル
  • 半径やスケール
  • 不透明度 など

PLYファイルの構造

PLYは ヘッダー部データ部 に分かれます。

  1. ヘッダー部

    • データ形式(ascii または binary
    • 頂点数、面数
    • 各属性の型と名称
  2. データ部

    • 頂点ごとに属性値を列挙(ASCII形式では1行ごと)

例(簡易的なASCII形式の点群)

ply
format ascii 1.0
element vertex 3
property float x
property float y
property float z
property uchar red
property uchar green
property uchar blue
end_header
0.0 0.0 0.0 255 0 0
1.0 0.0 0.0 0 255 0
0.0 1.0 0.0 0 0 255

NeRF由来のPLYと3DGS由来のPLYの違い

同じ「PLY形式」でも、中に含まれる属性は異なります。

  • NeRF由来のPLY

    • 位置(x, y, z)
    • 色(r, g, b)程度の最小限の属性
  • 3DGS由来のPLY

    • 上記に加えてガウス分布のスケール・回転・不透明度など、レンダリングに必要な追加属性を多数保持

注意点

この仕様の違いにより、同じPLY拡張子でもビューアや処理スクリプトによっては

  • 属性を正しく読み取れない
  • 追加情報が無視される
    といった表示や解析の不一致が発生することがあります。

🛠 3DGSでモデル作成:Postshotの利用

今回は、Postshot というGUIツールを使って、写真から3DGSモデルを作成しました。
参考: Postshotの使い方

手順概要

  1. 画像または動画を用意
    → 今回はNeRF公式のLEGOデータを利用
    GitHub: bmild/nerf(Data)
  2. Postshotにインポート
    → カメラパラメータ推定と3DGS変換を自動で実行
  3. PLY形式でエクスポート
    → このPLYは「位置+色+半径」情報を含む点群データ

🎮 MinecraftでのPLY応用アイデア

PLY形式の3Dデータは、点群(point cloud)の集合です。
「この点群をブロックとして置き換えれば、Minecraft内で再構成できるのでは?」という発想から、今回はそのアイデアをちょっと試してみます。

3DGSモデルは本来、ガウス分布を持った点群ですが、Pythonスクリプトを使えばMinecraftのブロック配置データに変換可能です。
座標と色情報をもとに、近い色のブロックを選んで配置することで、現実や3Dスキャンの結果をMinecraft内に再現できます。


応用例

  • 3DGSモデル → Minecraftブロック化
    点の位置と色から、最も近い色のブロックを選び、ワールドに配置
  • NeRFモデルのバーチャル展示
    フォトリアルな建物やオブジェクトをMinecraft上で再構築
  • 教育・研究用途
    フォトグラメトリやNeRF技術の成果を、Minecraftの中で直感的に可視化

🎮 PLY点群をMinecraftにブロック化する(3DGS対応)

📝 背景
3D Gaussian Splatting(3DGS)は通常、PLYに色情報を含めません。
そのため今回は色再現ではなく、すべて白い羊毛(WOOL)でブロック化する形で実装します。
実装の発想や流れは、以前作成した記事「PythonでMinecraftに静止画と動画を描画してみた」を参考にしています。


💻 コード全文

from plyfile import PlyData
from mcpi.minecraft import Minecraft
from mcpi import block

def build_pointcloud_scaled_thinned(ply_path, scale=50, thinning=2):
    # ① PLY読み込み
    plydata = PlyData.read(ply_path)
    vertices = plydata['vertex']

    # ② Minecraft接続
    mc = Minecraft.create("127.0.0.1")
    start_pos = mc.player.getTilePos()

    # ③ 座標範囲の取得
    xs = [v['x'] for v in vertices]
    ys = [v['y'] for v in vertices]
    zs = [v['z'] for v in vertices]

    min_x, max_y, min_z = min(xs), max(ys), min(zs)
    max_x, min_y, max_z = max(xs), min(ys), max(zs)

    placed = set()
    WOOL = block.WOOL.id

    # ④ 頂点ごとに処理
    for i, v in enumerate(vertices):
        # ⑤ 間引き
        if i % thinning != 0:
            continue

        # ⑥ スケーリングと座標変換
        x = int(round((v['x'] - min_x) * scale))
        y = int(round((max_y - v['y']) * scale))  # y軸反転
        z = int(round((v['z'] - min_z) * scale))

        coord = (start_pos.x + x, start_pos.y + y, start_pos.z + z)

        # ⑦ 重複防止
        if coord in placed:
            continue
        placed.add(coord)

        # ⑧ ブロック設置(白羊毛)
        mc.setBlock(*coord, WOOL, 0)

if __name__ == "__main__":
    # ⑨ 実行
    build_pointcloud_scaled_thinned("my_world_radius50.ply", scale=50, thinning=2)

📖 コード解説

  1. PLY読み込み
    PlyData.read() でPLYを読み込み、vertex要素から全頂点データを取得。

  2. Minecraft接続
    Minecraft.create() でサーバーに接続し、プレイヤーの位置を基準座標として取得。

  3. 座標範囲の取得
    x, y, z の最小値・最大値を求め、後のスケーリングや座標反転に使用。

  4. 頂点ごとに処理
    点群の各頂点を順番に処理。

  5. 間引き
    thinning間隔で点を利用。点群の量が1万と多いので、点群密度が高い場合の負荷軽減に有効。

  6. スケーリングと座標変換

    • PLYは通常、座標を (1.4534..., 2.0987..., 3.4839...) といった実数(x,y,z)で保存しています。
    • しかしMinecraftはブロック単位(1ブロック = 1整数座標)で構築されるため、そのままだと非常に小さく見えてしまいます。
    • そこで、PLY座標から最小値を引いて0基準に変換した後、scale倍(例: 100倍)することで、Minecraftの世界で人間サイズに近い大きさに再現します。
    • y軸はPLYとMinecraftで方向が逆のため、上下反転を行います。
  7. 重複防止
    配置済みの座標はsetに記録し、再設置を回避。

  8. ブロック設置(白羊毛)
    mc.setBlock()でブロックを設置。
    3DGSのPLYには色情報がないため、今回は白羊毛で統一。

  9. 実行
    ファイル名・スケール・間引き率を指定して関数を実行。

では、その「結果」の部分もZenn記事風に整理して、文章と見出しを整えつつ、画像を挿入する形にまとめてみます。

🏁 結果

元のPLYモデル(3DGS出力)は、色情報が含まれていないため、Minecraft内では白い羊毛で再現しました。

元画像

Minecraft上で再現した結果

色は反映されていませんが、点群構造をMinecraftブロックで再現できることは確認できました。

さらに、PLYに色情報があれば色付きブロックや建物の再現も可能です。

今回の結果から、PLYデータをMinecraftに応用できる道を見つけられたと言えますね。

🔮 まとめと展望

  • 3DGSはNeRFの高速化版として注目される技術
  • PostshotでPLY形式にエクスポート可能
  • Pythonを使えばMinecraftなど別環境での再利用が容易
  • 教育・アート・ゲームなど幅広く応用可能

次回は、この方式の確認を詳しくみていようと思います。

Discussion