今回はOpen3Dでインプットした3Dモデルからジオメトリ数を取得します。
〇環境
・Windows11PC
・Anaconda3
・Python3.11
〇ジオメトリとは?
ジオメトリとは3Dモデルのメッシュにおけるデータヒエラルキーの一つです。
3Dモデルはオブジェクトと呼ばれる単位でここの区別を行っています。一番小さなヒエラルキーデータはポリゴンとそれを構成する頂点ですが、ポリゴン同士でつながって構成されるひとまとまりの形状をジオメトリと呼びます。
以下のような例では、オブジェクトとしては1つですが、2つのジオメトリで構成されれていると言えます。
今回はOpen3Dでこのジオメトリ数を取得することを行います。
〇コード
import open3d as o3d
import numpy as np
def count_submeshes(mesh):
# 各三角形にクラスタ番号を割り当てる
triangle_clusters, _, _ = mesh.cluster_connected_triangles()
triangle_clusters = np.asarray(triangle_clusters)
# ユニークなクラスタの数がサブメッシュの数
return len(np.unique(triangle_clusters))
if __name__ == "__main__":
mesh = o3d.io.read_triangle_mesh("input/defaut.obj")
if mesh.is_empty():
print("メッシュが空です。")
else:
num_submeshes = count_submeshes(mesh)
print(f"サブメッシュの数(ジオメトリ数): {num_submeshes}")
このコードを実行すると以下のような結果が返されます。

(openvdb_env) D:\AI\openvdb>python geometry.py サブメッシュの数(ジオメトリ数): 2
今回のコードはポリゴンごとに番号を付けています。
mesh.cluster_connected_triangles()は連結成分を取得する関数です。
隣接する三角形が同じグループに属するかどうかを、三角形同士が「エッジを共有しているか」で判定します。
この属性の値によってジオメトリ(=サブメッシュ)の数を取得できます。
そのためフラットシェーディングでは、各面ごとに法線が固定されるため、通常は面ごとに頂点が重複して作られ隣接する三角形が共有する頂点がなくなり、連結とみなさないことによりcluster_connected_triangles() では多くの三角形が「個別の」サブメッシュとして認識され、サブメッシュの数が非常に多くなるという問題が存在します。

フラットシェーディングの場合は (openvdb_env) D:\AI\openvdb>python geometry.py サブメッシュの数(ジオメトリ数): 1077 同じモデルでスムースシェーディングの場合 (openvdb_env) D:\AI\openvdb>python geometry.py サブメッシュの数(ジオメトリ数): 2
この辺りが課題として残っています。