MRが楽しい

MRやVRについて学習したことを書き残す

Blender2.9で利用可能なpythonスクリプトを作る その82(全メッシュに対するポリゴン数指定のリダクション)

本日は Blender の技術調査枠です。
Blender2.9で利用可能なpythonスクリプトを作ります。

メッシュのポリゴン数を削減する

メッシュのポリゴン数を削減するには[デシメート]モディファイアを利用します。
ratio 変数からポリゴン削減の比率を設定することができます。
docs.blender.org

比率を求めるためのポリゴン数は Mesh データの calc_loop_triangles() 関数から算出します。
docs.blender.org

サンプルコード

指定数のポリゴン(三角面)数になる比率を計算し、全てのメッシュに[デシメート]モディファイアを反映します。
ポリゴン数が少ないオブジェクトが破綻しないように引数から最低のポリゴン数を指定することもできます。
・Script_apply_decimate_allmeshcount.py

# bpyインポート
import bpy

# 全メッシュを対象に指定のポリゴン数まで削減する
def apply_decimate_allmeshcount(arg_trianglecount=10000, arg_mintcount=0) -> bool:
    """全メッシュを対象に指定のポリゴン数まで削減する

    Keyword Arguments:
        arg_trianglecount {int} -- 削減後の指定ポリゴン数 (default: {10000})
        arg_mintcount {int} -- オブジェクトの最低ポリゴン数 (default: {0})

    Returns:
        Bool -- 実行正否
    """

    # 全メッシュの総ポリゴン(三角面)数を取得する
    current_trianglecount = count_alltriangles_mesh()

    # 削減の比率を計算する
    target_ratio = 1.0

    # 指定のポリゴン数より現在のポリゴン数が多いか確認する
    if current_trianglecount > arg_trianglecount:
        # 指定のポリゴン数まで削減するための比率を計算する
        target_ratio = arg_trianglecount / current_trianglecount

    # 全オブジェクトデータを取得する
    for obj in bpy.data.objects:
        # オブジェクトに反映する削減比率
        obj_ratio = target_ratio

        # オブジェクトのポリゴン数を取得する
        obj_trianglecount = count_triangles_mesh(obj)

        # 対象のオブジェクトが既に最低ポリゴン数を下回っていないかチェックする
        if obj_trianglecount < arg_mintcount:
            # 下回っていれば対象のオブジェクトは処理しない
            continue

        # 削減後に指定の最低ポリゴン数を下回らないかチェックする
        if (obj_trianglecount * target_ratio) < arg_mintcount:
            # 下回るようであれば最低ポリゴン数までの削減比率を再計算する
            obj_ratio = arg_mintcount / obj_trianglecount

        # オブジェクトを指定の比率でポリゴン削減する
        apply_decimate_mesh(arg_targetobject=obj, arg_decimateratio=obj_ratio)

    return True

# 対象オブジェクトを指定の比率でポリゴン削減する
# モディファイア追加の種類とマニュアル
# (https://docs.blender.org/api/current/bpy.ops.object.html#bpy.ops.object.gpencil_modifier_add)
def apply_decimate_mesh(arg_targetobject, arg_decimateratio=1.0) -> bool:
    """対象オブジェクトを指定の比率でポリゴン削減する

    Keyword Arguments:
        arg_targetobject {bpy.types.Object} -- 対象オブジェクト
        arg_decimateratio {float} -- 削減比率 (default: {1.0})

    Returns:
        Bool -- 実行正否
    """

    # 指定オブジェクトがメッシュか確認する
    if arg_targetobject.type != 'MESH':
        # 指定オブジェクトが存在しない場合は処理しない
        return False

    # 変更オブジェクトをアクティブに変更する
    bpy.context.view_layer.objects.active = arg_targetobject

    # 「ポリゴン数削減」モディファイアを追加する
    # ポリゴン数削減モディファイアのインタフェース
    # (https://docs.blender.org/api/current/bpy.types.DecimateModifier.html)
    bpy.ops.object.modifier_add(type='DECIMATE')

    # 追加されたモディファイアを取得する
    decimate_modifier = arg_targetobject.modifiers[-1]

    # 削減の比率を設定する
    decimate_modifier.ratio = arg_decimateratio

    # 「ポリゴン数削減」モディファイアを適用する
    bpy.ops.object.modifier_apply(modifier=decimate_modifier.name)
    
    return True

# 指定メッシュの三角面数を取得する
def count_alltriangles_mesh() -> int:
    """全メッシュの総三角面数を取得する
    
    Keyword Arguments:

    Returns:
        int -- 三角面数(取得失敗時:0)
    """

    # 総三角面数のカウンタ
    triangles_count = 0

    # 全メッシュデータを取得する
    for obj in bpy.data.objects:
        # 三角面数を加算する
        triangles_count += count_triangles_mesh(obj)

    return triangles_count

# 指定メッシュの三角面数を取得する
def count_triangles_mesh(arg_object) -> int:
    """指定メッシュの三角面数を取得する
    
    Keyword Arguments:
        arg_objectname {bpy.types.Object} -- 対象オブジェクト

    Returns:
        int -- 三角面数(取得失敗時:0)
    """

    # 指定オブジェクトがメッシュか確認する
    if arg_object.type != 'MESH':
        # 指定オブジェクトが存在しない場合は処理しない
        return 0

    # Meshデータを取得する
    # メッシュアクセスのマニュアル
    # (https://docs.blender.org/api/current/bpy.types.Mesh.html)
    msh = arg_object.data

    # 三角面を計算する(結果はloop_trianglesに保存される)
    msh.calc_loop_triangles()

    # 三角面数を取得する
    triangles_count = len(msh.loop_triangles)

    return triangles_count

# 関数の実行例
apply_decimate_allmeshcount(arg_trianglecount=10000, arg_mintcount=20)

以下は削減後のポリゴン数を 10,000、オブジェクト辺りの最低ポリゴン数を 20 に指定した実行例です。
・実行前
f:id:bluebirdofoz:20211002211630j:plain

・実行後
f:id:bluebirdofoz:20211002211652j:plain