MRが楽しい

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

Blender2.8で利用可能なpythonスクリプトを作る その9(クリーンアップ)

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

孤立/重複頂点削除のクリーンアップを実行

指定オブジェクトに孤立/重複頂点削除のクリーンアップの処理を実行します。
スクリプト例ではオブジェクトに以下のクリーンアップを実行します。

大きさ0を融解:面積が0の面を削除し、1つの頂点にまとめる
孤立を削除:どの面にもつながっていない辺や頂点を削除する
重複頂点を削除:重複している頂点を1つの頂点にまとめる

・cleanup_mesh_object.py

# bpyインポート
import bpy

# オブジェクトに以下のクリーンアップを実行
# ・大きさ0を融解:面積が0の面を削除し、1つの頂点にまとめる
# ・孤立を削除:どの面にもつながっていない辺や頂点を削除する
# ・重複頂点を削除:重複している頂点を1つの頂点にまとめる
def cleanup_mesh_object(arg_objectname="Default") -> bool:
    """オブジェクトにクリーンアップを実行
    ・大きさ0を融解:面積が0の面を削除し、1つの頂点にまとめる
    ・孤立を削除:どの面にもつながっていない辺や頂点を削除する
    ・重複頂点を削除:重複している頂点を1つの頂点にまとめる
    
    Keyword Arguments:
        arg_objectname {str} -- 指定オブジェクト名 (default: {"Default"})

    Returns:
        bool -- 実行の正否
    """

    # 他のオブジェクトに操作を適用しないよう全てのオブジェクトを走査する
    for ob in bpy.context.scene.objects:
        # 非選択状態に設定する
        ob.select_set(False)

    # 指定オブジェクトを取得する
    # (get関数は対象が存在しない場合 None が返る)
    targetob = bpy.data.objects.get(arg_objectname)

    # 指定オブジェクトが存在するか確認する
    if targetob == None:
        # 指定オブジェクトが存在しない場合は処理しない
        return False

    # 変更オブジェクトをアクティブに変更する
    bpy.context.view_layer.objects.active = targetob
  
    # 編集モードに移行する
    bpy.ops.object.mode_set(mode='EDIT', toggle=False)

    # 頂点を全選択した状態とする
    bpy.ops.mesh.select_all(action='SELECT') 

    # 大きさ0を融解(結合距離 0.0001)
    bpy.ops.mesh.dissolve_degenerate(threshold=0.0001)

    # 変更を反映するため再び頂点を全選択
    bpy.ops.mesh.select_all(action='SELECT') 

    # 孤立を削除(頂点、辺のみ)
    bpy.ops.mesh.delete_loose(use_verts=True, use_edges=True, use_faces=False)

    # 孤立を削除で全選択が解除されるので再び頂点を全選択
    bpy.ops.mesh.select_all() 

    # 重複頂点を削除(結合距離 0.0001、非選択部の結合無効)
    bpy.ops.mesh.remove_doubles(threshold=0.0001, use_unselected=False)

    # オブジェクトモードに移行する
    bpy.ops.object.mode_set(mode='OBJECT', toggle=False)

    return True

# 関数の実行例
cleanup_mesh_object("Cube")

f:id:bluebirdofoz:20200103220555j:plain

穴を埋めるクリーンアップを実行

指定オブジェクトに[穴を埋める]のクリーンアップの処理を実行します。
・fillholes_mesh_object.py

# bpyインポート
import bpy

# オブジェクトに以下のクリーンアップを実行
# ・穴を埋める:辺ループの穴を埋める(辺数:4)
def fillholes_mesh_object(arg_objectname="Default") -> bool:
    """オブジェクトにクリーンアップを実行
    ・穴を埋める:辺ループの穴を埋める(辺数:4)
    
    Keyword Arguments:
        arg_objectname {str} -- 指定オブジェクト名 (default: {"Default"})

    Returns:
        bool -- 実行の正否
    """
    
    # 他のオブジェクトに操作を適用しないよう全てのオブジェクトを走査する
    for ob in bpy.context.scene.objects:
        # 非選択状態に設定する
        ob.select_set(False)

    # 指定オブジェクトを取得する
    # (get関数は対象が存在しない場合 None が返る)
    targetob = bpy.data.objects.get(arg_objectname)

    # 指定オブジェクトが存在するか確認する
    if targetob == None:
        # 指定オブジェクトが存在しない場合は処理しない
        return False

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

    # 編集モードに移行する
    bpy.ops.object.mode_set(mode='EDIT', toggle=False)

    # 頂点を全選択した状態とする
    bpy.ops.mesh.select_all(action='SELECT') 

    # 穴を埋める(辺数:4)
    bpy.ops.mesh.fill_holes(sides=4)

    # オブジェクトモードに移行する
    bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
  
    return True

# 関数の実行例
fillholes_mesh_object("Sphere")

f:id:bluebirdofoz:20200103220609j:plain