夜風のMixedReality

xRと出会って変わった人生と出会った技術を書き残すためのGeekなHoloRangerの居場所

Pythonを用いてOBJのモデルをデシメートを行う

本日はPython、3Dモデリング枠です。

 BlenderやMayaといった3Dモデリングに特化したDCCツールはPythonで動いており、Pythonライブラリを使用したプログラマブルな機能へアクセスすることができます。

 この理由はC#などでは直接C++コードを読み込むことが一般的ではないのに対してPythonC/C++と直接インターフェースするためのツールとライブラリを持っているためであり、3DCGに関するオープンソースライブラリの多くがPythonもしくはC++で提供されているためです。

 今回はPythonを用いてOBJのモデルをデシメートュする実装を行います。

 今回は3DCGを扱うライブラリとしてOpen3Dを使用します。

https://github.com/isl-org/Open3D

 Open3Dは3Dデータの処理において便利なライブラリであり、3Dデータ構造に基づきダウンサンプリング、法線、メッシュといった様々な変更の機能が提供されています。

 

〇環境

・Windows11PC

・Anaconda Propmpt

・Python3.11

・Open3D

〇Open3Dを用いたOBJモデルのデシメート

仮想環境を作成します。

conda create -n open3d_env python=3.10
conda activate open3d_env

conda-forgeを使用してtrimesh,pymeshlab,open3dをインストールします。open3dを含むこれらが今回使用するライブラリです。

pip install trimesh pymeshlab open3d

新規のPythonファイルを作成しますremesh_open3d.py

Pythonコード内部は次のようになります。

import open3d as o3d
import os

def remesh_obj(input_folder, output_folder, reduction_ratio=0.5):
    """
 summary   
 指定フォルダ内のOBJファイルをリメッシュ(ポリゴン削減)し、出力フォルダに保存する。

    Args:
        input_folder (str): 入力フォルダのパス
        output_folder (str): 出力フォルダのパス
        reduction_ratio (float): ポリゴン削減率 (0.0 - 1.0)
    """
    # 出力フォルダを作成(存在しない場合)
    os.makedirs(output_folder, exist_ok=True)

    # フォルダ内のすべてのOBJファイルを処理
    for file_name in os.listdir(input_folder):
        if file_name.lower().endswith(".obj"):
            file_path = os.path.join(input_folder, file_name)
            print(f"Processing: {file_path}")

            # OBJファイルを読み込む
            mesh = o3d.io.read_triangle_mesh(file_path)

            # ポリゴン数を取得
            original_triangle_count = len(mesh.triangles)
            target_triangle_count = int(original_triangle_count * reduction_ratio)
            
            # ログを出力
            print(f"Original: {original_triangle_count} triangles → Target: {target_triangle_count} triangles")

            # メッシュのポリゴン数を削減
            mesh = mesh.simplify_quadric_decimation(target_triangle_count)

            # 出力ファイルパスを設定
            output_file_path = os.path.join(output_folder, f"{os.path.splitext(file_name)[0]}_remeshed.obj")

            # ファイルを保存
            o3d.io.write_triangle_mesh(output_file_path, mesh)
            print(f"Remeshed and saved: {output_file_path}\n")

if __name__ == "__main__":
    input_folder = "input"   # 入力フォルダ
    output_folder = "output" # 出力フォルダ
    remesh_obj(input_folder, output_folder, reduction_ratio=0.5)  # 50% にポリゴン削減

最後にinputフォルダおよびoutputフォルダを作成します。

最後にinputフォルダに3Dモデルを配置しAnacondaでPythonコードを実行します。

python remesh_open3d.py

これを実行すると正常に処理が完了するとBlender_remeshed.objがoutputフォルダ内に生成されます。

これを見ると元のメッシュに対してリメッシュとポリゴン数の削減、スムースの3つが実行できていることが確認できます。

本日は以上です。