夜風のMixedReality

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

Blenderでポリゴン数が多い順にオブジェクトを表示する その④ソートモードを作成する

本日はBlenderPython枠です。

時間が空いてしまっていましたが以前Blenderでポリゴン数が多い順にオブジェクトを表示するPythonコードを書きました。

redhologerbera.hatenablog.com

今回はこちらの更新を行います。

〇以前のコード

import bpy

class OBJECT_OT_calculate_polygons(bpy.types.Operator):
    bl_idname = "object.calculate_polygons"
    bl_label = "Calculate Polygons"

    def execute(self, context):
        selected_objects = bpy.context.selected_objects
        for obj in selected_objects:
            if obj.type == 'MESH':
                poly_count = len(obj.data.polygons)
                obj["poly_count"] = poly_count
        return {'FINISHED'}

class CustomPanel(bpy.types.Panel):
    bl_idname = "OBJECT_PT_custom_panel"
    bl_label = "Custom Panel"
    bl_space_type = 'VIEW_3D'
    bl_region_type = 'UI'
    bl_category = 'Custom'

    def draw(self, context):
        layout = self.layout
        layout.operator("object.calculate_polygons", text="Calculate Polygons")
        
        for obj in bpy.context.selected_objects:
            if obj.type == 'MESH':
                row = layout.row()
                row.label(text=f'Object: {obj.name}')
                row.prop(obj, '["poly_count"]', text="Polygons")

def register():
    bpy.utils.register_class(OBJECT_OT_calculate_polygons)
    bpy.utils.register_class(CustomPanel)

def unregister():
    bpy.utils.unregister_class(OBJECT_OT_calculate_polygons)
    bpy.utils.unregister_class(CustomPanel)

if __name__ == "__main__":
    register()

実行すると、3Dビューポート内で "Custom" タブにカスタムパネルが表示され、選択したメッシュオブジェクトのポリゴン数を計算および表示できます。

チェックボックスの追加と三角ポリゴン表示

上記コードではメッシュの数=ポリゴン数として計測しています。

これによって本来三角ポリゴンとしては2ポリゴンである正方形メッシュも1として表示されてしまう問題があります。

今回は任意に3角ポリゴンとして計算するモードを実装します。

まずはUIを実装します。

UIパネルであるCustomPanel()クラスのUI描画であるdraw関数に一行追加します。

class CustomPanel(bpy.types.Panel):
    bl_idname = "OBJECT_PT_custom_panel"
    bl_label = "Custom Panel"
    bl_space_type = 'VIEW_3D'
    bl_region_type = 'UI'
    bl_category = 'Custom'

    def draw(self, context):
        layout = self.layout
        layout.operator("object.calculate_polygons", text="Calculate Polygons")
        layout.prop(context.scene, 'triangles_mode', text="Triangles Mode")#追加

        
        for obj in bpy.context.selected_objects:
            if obj.type == 'MESH':
                row = layout.row()
                row.label(text=f'Object: {obj.name}')
                row.prop(obj, '["poly_count"]', text="Polygons")

次に定義したチェックボックスを使うためのオペレータを定義します。

bpy.types.Scene.triangles_mode = bpy.props.BoolProperty(
    name="Triangles Mode",
    description="If enabled, perform the calculation as triangles",
    default=True,
)

この変更によってチェックボックスが表示されます。

次にチェックボックスのオンオフによって処理を変えていきます。

具体的にはオペレータークラスのexcute内で、if文としてobj.triangles_mode(定義したチェックボックス)のbool値を取得します。

class OBJECT_OT_calculate_polygons(bpy.types.Operator):
    bl_idname = "object.calculate_polygons"
    bl_label = "Calculate Polygons"

    def execute(self, context):
        selected_objects = bpy.context.selected_objects
        for obj in selected_objects:
            if obj.type == 'MESH':
                poly_count = 0  # ポリゴン数の初期値を設定
                if obj.triangles_mode:
                    # 編集モードに切り替えてすべてのメッシュ要素を選択
                    bpy.context.view_layer.objects.active = obj 
                    bpy.ops.object.mode_set(mode='EDIT') #editorモードにする
                    bpy.ops.mesh.select_all(action='SELECT')#すべてのメッシュを取得

                    # 三角化モディファイアを適用
                    bpy.ops.mesh.quads_convert_to_tris(quad_method='BEAUTY', ngon_method='BEAUTY')

                    # 編集モードを終了
                    bpy.ops.object.mode_set(mode='OBJECT')

                # ポリゴン数を計算
                poly_count = len(obj.data.polygons)
                obj["poly_count"] = poly_count

        return {'FINISHED'}

一度三角化モディファイアを適応した状態でメッシュの値を取得することで▽ポリゴンとしてのポリゴン数を取得できます。

これを実行すると次のようになります。

Cubeのポリゴン数が12になったことを確認できました。

本日は以上です。

〇コード全文

import bpy

bpy.types.Scene.triangles_mode = bpy.props.BoolProperty(
    name="Triangles Mode",
    description="If enabled, perform the calculation as triangles",
    default=True,
)

class OBJECT_OT_calculate_polygons(bpy.types.Operator):
    bl_idname = "object.calculate_polygons"
    bl_label = "Calculate Polygons"

    def execute(self, context):
        triangles_mode = bpy.context.scene.triangles_mode  # ここで 'triangles_mode' を正しく取得
        selected_objects = bpy.context.selected_objects
        for obj in selected_objects:
            if obj.type == 'MESH':
                poly_count = 0  # ポリゴン数の初期値を設定
                if triangles_mode:
                    # 編集モードに切り替えてすべてのメッシュ要素を選択
                    bpy.context.view_layer.objects.active = obj
                    bpy.ops.object.mode_set(mode='EDIT')
                    bpy.ops.mesh.select_all(action='SELECT')

                    # 三角化モディファイアを適用
                    bpy.ops.mesh.quads_convert_to_tris(quad_method='BEAUTY', ngon_method='BEAUTY')

                    # 編集モードを終了
                    bpy.ops.object.mode_set(mode='OBJECT')

                # ポリゴン数を計算
                poly_count = len(obj.data.polygons)
                obj["poly_count"] = poly_count

        return {'FINISHED'}

class CustomPanel(bpy.types.Panel):
    bl_idname = "OBJECT_PT_custom_panel"
    bl_label = "Custom Panel"
    bl_space_type = 'VIEW_3D'
    bl_region_type = 'UI'
    bl_category = 'Custom'

    def draw(self, context):
        layout = self.layout
        layout.operator("object.calculate_polygons", text="Calculate Polygons")
        layout.prop(context.scene, 'triangles_mode', text="Triangles Mode")
        
        for obj in bpy.context.selected_objects:
            if obj.type == 'MESH':
                row = layout.row()
                row.label(text=f'Object: {obj.name}')
                row.prop(obj, '["poly_count"]', text="Polygons")


def register():
    bpy.utils.register_class(OBJECT_OT_calculate_polygons)
    bpy.utils.register_class(CustomPanel)

def unregister():
    bpy.utils.unregister_class(OBJECT_OT_calculate_polygons)
    bpy.utils.unregister_class(CustomPanel)

if __name__ == "__main__":
    register()