本日はPython枠です。
先日Open3Dを用いたポリゴン削減を行いました。
今回はブーリアン演算を実装していきます。
先日よりはてなブログのサーバーが不具合があったようで2日ぶりの記事になります。
〇環境
・Windows11PC
・Open3D
・Anaconda Prompt
・Python3.11
〇ブーリアンとは?
ブーリアンは複数の3Dオブジェクトの体積の足し算、引き算を行う処理です。
BlenderやMayaでは標準で搭載されている機能ですが、Unityなどで独自に実装を行おうとするとそのアルゴリズムは複雑です。
open3Dではv0.16以降でブーリアンをサポートしています。
〇実装
今回はinputフォルダおよびoutputフォルダを用意しinputフォルダに配置した2つのobjを処理し、outputフォルダにエクスポートする処理になります。
import open3d as o3d
import open3d.core as o3c
import os
def boolean_operation(input_folder, output_folder, operation="union"):
"""
指定フォルダ内の2つのOBJファイルに対してブーリアン演算を行う。
Args:
input_folder (str): 入力フォルダのパス
output_folder (str): 出力フォルダのパス
operation (str): "union"(和)、"difference"(差)、"intersection"(交差)の3種類から選択
"""
os.makedirs(output_folder, exist_ok=True)
# OBJファイルの取得
obj_files = [f for f in os.listdir(input_folder) if f.lower().endswith(".obj")]
if len(obj_files) < 2:
print("エラー: OBJファイルが2つ必要です")
return
obj1_path = os.path.join(input_folder, obj_files[0])
obj2_path = os.path.join(input_folder, obj_files[1])
print(f"Processing: {obj1_path} and {obj2_path}")
# Open3D Tensor Mesh としてロード
mesh1 = o3d.io.read_triangle_mesh(obj1_path)
mesh2 = o3d.io.read_triangle_mesh(obj2_path)
# Mesh を tensor ベースのフォーマットに変換
mesh1_t = o3d.t.geometry.TriangleMesh.from_legacy(mesh1)
mesh2_t = o3d.t.geometry.TriangleMesh.from_legacy(mesh2)
# ブーリアン演算の実行
if operation == "union":
result = mesh1_t.boolean_union(mesh2_t)
elif operation == "difference":
result = mesh1_t.boolean_difference(mesh2_t)
elif operation == "intersection":
result = mesh1_t.boolean_intersection(mesh2_t)
else:
print("エラー: operationは 'union', 'difference', 'intersection' のいずれかを指定してください")
return
# Open3D 形式に変換し、出力ファイルとして保存
result_legacy = result.to_legacy()
output_file = os.path.join(output_folder, f"boolean_{operation}.obj")
o3d.io.write_triangle_mesh(output_file, result_legacy)
print(f"ブーリアン演算完了: {output_file}")
if __name__ == "__main__":
input_folder = "input"
output_folder = "output"
boolean_operation(input_folder, output_folder, operation="union") # 和演算
この処理を実装するとブーリアンが行われます。
元メッシュ(左)と比較するとブーリアンによって閉じたメッシュとして構成されていることがわかると思います。

以上でブーリアンを実装できましたが、問題としてはブーリアンを行った場合ジオメトリが変わるため、メッシュの法線を再計算しなければならないのですが、現状では法線が崩れてしまう問題があります。

この法線に関してもOpen3Dに良い機能がないか次回以降見て生きたと思います。
本日は以上です。