MRが楽しい

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

Blender3.0で利用可能なpythonスクリプトを作る その93(指定の頂点グループに所属している頂点の数を取得する)

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

指定の頂点グループに所属している頂点の数を取得する

頂点と頂点グループの関連情報は Vertex データ側に情報が保持されています。
docs.blender.org

このため、頂点グループに所属している頂点の数を計算するには通常、以下のように頂点側の情報から算出する必要があります。

# 指定オブジェクトの全頂点を走査する
for vert in arg_object.data.vertices:
    # 頂点が所属している頂点グループのインデックスリストを取得する
    for groupinfo in vert.groups:
        # 指定の頂点グループに所属していればカウントアップする
        if groupinfo.group == check_vertexgroup_index:
            result_count = result_count + 1

もし頂点グループ側から頂点の数を計算する場合は以下のようにエラーをキャッチする必要があります。

# 指定オブジェクトの全頂点を走査する
for vert in arg_object.data.vertices:
    try:
        # ウェイト情報を参照できるならカウントアップする
        check_vertexgroup.weight(vert.index)
        result_count = result_count + 1
    except RuntimeError:
        # 頂点グループに所属していない場合はエラーが発生するのでパスする
        pass

サンプルスクリプト

前述の2つの方法を利用して作成した頂点グループの頂点の数を計算するサンプルスクリプトを作成しました。
・Script_count_vertexgroup_pattern01.py

# bpyインポート
import bpy

def count_weight_vertexgroup(
    arg_object:bpy.types.Object, arg_vertexgroup_name:str) -> int:
    """指定の頂点グループに所属している頂点の数を取得する(頂点の参照から算出)

    Keyword Arguments:
        arg_object {bpy.types.Object} -- 指定オブジェクト
        arg_vertexgroupname {str} -- 指定の頂点グループ名

    Returns:
        int -- 頂点グループに含まれる頂点数
    """

    # 指定オブジェクトに指定の頂点グループが含まれるかチェックする
    check_vertexgroup = arg_object.vertex_groups.get(arg_vertexgroup_name)
    if check_vertexgroup == None:
        return 0
    
    # カウント用変数
    result_count = 0

    # 指定の頂点グループについて頂点グループリストでのインデックス番号を取得する
    check_vertexgroup_index = check_vertexgroup.index

    # 指定オブジェクトの全頂点を走査する
    for vert in arg_object.data.vertices:
        # 頂点が所属している頂点グループのインデックスリストを取得する
        for groupinfo in vert.groups:
            # 指定の頂点グループに所属していればカウントアップする
            if groupinfo.group == check_vertexgroup_index:
                result_count = result_count + 1

    # カウント結果を返却する
    return result_count

# オブジェクトモードへの移行
# モード切替のマニュアル
# (https://docs.blender.org/api/current/bpy.ops.object.html#bpy.ops.object.mode_set)
def set_mode_object() -> bool:
    """オブジェクトモードへの移行

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

    # オブジェクトモードに移行する
    # モード切替のマニュアル
    # (https://docs.blender.org/api/current/bpy.ops.object.html#bpy.ops.object.mode_set)
    # mode:OBJECT オブジェクトモードに切り替え
    # toggle:True の場合、既に編集モードの時、オブジェクトモードに戻る
    bpy.ops.object.mode_set(mode='OBJECT', toggle=False)

    return True

# 選択中の頂点から新規頂点グループを作成してグループ名を取得する
def make_vertexgroup() -> str:
    """選択中の頂点から新規頂点グループを作成してグループ名を取得する

    Keyword Arguments:

    Returns:
        str -- 新規頂点グループ名
    """

    # 現在のモードが「編集モード(EDIT_MESH)」かチェックする
    if check_viewmode('EDIT_MESH') == False :
        return ""

    # 編集中のアクティブオブジェクトを取得する
    active_object = bpy.context.view_layer.objects.active

    # 選択中の頂点に新規頂点グループを割り当てる
    bpy.ops.object.vertex_group_assign_new()

    # 作成した頂点グループのインデックス番号を取得する
    make_index = active_object.vertex_groups.active_index

    # 作成した頂点グループのグループ名を返却する
    return active_object.vertex_groups[make_index].name

# 現在のモードが指定のモードかチェックする
def check_viewmode(arg_checktype:str) -> bool:
    """現在のモードが指定のモードかチェックする

    Keyword Arguments:
        arg_checktype {str} -- 比較するモード名

    Returns:
        str -- 現在のモード
    """

    # 現在のモードをチェックする
    # (https://docs.blender.org/api/current/bpy.context.html#bpy.context.mode)
    modetype = bpy.context.mode

    return (arg_checktype == modetype)

# 関数の実行例
# 選択中の頂点から新規頂点グループを作成してグループ名を取得する
make_groupname = make_vertexgroup()
# 変更をオブジェクトデータに反映するため、一旦オブジェクトモードに戻る
set_mode_object()
# 頂点データから頂点グループに所属している頂点数を算出つする
vertexgroup_count = count_weight_vertexgroup(bpy.context.view_layer.objects.active,make_groupname)
# 結果をコンソールに表示する
print("VertexGroup count : " + str(vertexgroup_count))

f:id:bluebirdofoz:20211227221552j:plain
f:id:bluebirdofoz:20211227221602j:plain

・Script_count_vertexgroup_pattern02.py

# bpyインポート
import bpy

def count_weight_vertexgroup(
    arg_object:bpy.types.Object, arg_vertexgroup_name:str) -> int:
    """指定の頂点グループに所属している頂点の数を取得する(頂点グループの参照から算出)

    Keyword Arguments:
        arg_object {bpy.types.Object} -- 指定オブジェクト
        arg_vertexgroup_name {str} -- 指定の頂点グループ名

    Returns:
        int -- 頂点グループに含まれる頂点数
    """

    # 指定オブジェクトに指定の頂点グループが含まれるかチェックする
    check_vertexgroup = arg_object.vertex_groups.get(arg_vertexgroup_name)
    if check_vertexgroup == None:
        return 0
    
    # カウント用変数
    result_count = 0

    # 指定の頂点グループについて頂点グループリストでのインデックス番号を取得する
    check_vertexgroup_index = check_vertexgroup.index

    # 指定オブジェクトの全頂点を走査する
    for vert in arg_object.data.vertices:
        try:
            # ウェイト情報を参照できるならカウントアップする
            check_vertexgroup.weight(vert.index)
            result_count = result_count + 1
        except RuntimeError:
            # 頂点グループに所属していない場合はエラーが発生するのでパスする
            pass

    # カウント結果を返却する
    return result_count

# 選択中の頂点から新規頂点グループを作成してグループ名を取得する
def make_vertexgroup() -> str:
    """選択中の頂点から新規頂点グループを作成してグループ名を取得する

    Keyword Arguments:

    Returns:
        str -- 新規頂点グループ名
    """

    # 現在のモードが「編集モード(EDIT_MESH)」かチェックする
    if check_viewmode('EDIT_MESH') == False :
        return ""

    # 編集中のアクティブオブジェクトを取得する
    active_object = bpy.context.view_layer.objects.active

    # 選択中の頂点に新規頂点グループを割り当てる
    bpy.ops.object.vertex_group_assign_new()

    # 作成した頂点グループのインデックス番号を取得する
    make_index = active_object.vertex_groups.active_index

    # 作成した頂点グループのグループ名を返却する
    return active_object.vertex_groups[make_index].name

# 現在のモードが指定のモードかチェックする
def check_viewmode(arg_checktype:str) -> bool:
    """現在のモードが指定のモードかチェックする

    Keyword Arguments:
        arg_checktype {str} -- 比較するモード名

    Returns:
        str -- 現在のモード
    """

    # 現在のモードをチェックする
    # (https://docs.blender.org/api/current/bpy.context.html#bpy.context.mode)
    modetype = bpy.context.mode

    return (arg_checktype == modetype)

# 関数の実行例
# 選択中の頂点から新規頂点グループを作成してグループ名を取得する
make_groupname = make_vertexgroup()
# 頂点グループの参照から頂点グループに所属している頂点数を算出つする
vertexgroup_count = count_weight_vertexgroup(bpy.context.view_layer.objects.active,make_groupname)
# 結果をコンソールに表示する
print("VertexGroup count : " + str(vertexgroup_count))

f:id:bluebirdofoz:20211227221616j:plain
f:id:bluebirdofoz:20211227221626j:plain

参考ページ

blender.stackexchange.com