MRが楽しい

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

BlenderのPythonでローカル座標とグローバル座標の頂点座標を確認する

本日は Blender の調査枠です。
BlenderPythonでローカル座標とグローバル座標の頂点座標を確認したので記事に記録しておきます。

頂点座標のローカル座標とグローバル座標

サンプルとしてスケールを3倍にした Cube オブジェクトを用意しました。
f:id:bluebirdofoz:20210811222729j:plain

[編集モード]に切り替えて、頂点座標を確認してみます。
[ローカル]座標で確認すると、スケールの影響を受けない Mesh 内での座標が表示されます。
f:id:bluebirdofoz:20210811222739j:plain

[グローバル]座標で確認すると、スケールの影響を受けた全体での座標が表示されます。
f:id:bluebirdofoz:20210811222750j:plain

pythonでの座標の取得結果

Python スクリプトで頂点を参照して、その座標情報を表示するスクリプトを作成しました。
・mesh_verts_print.py

# bpyインポート
import bpy
# メッシュ操作のため
import bmesh

# 指定オブジェクトの頂点情報を表示する
def mesh_verts_print(arg_objectname="Default") -> bool:
    """指定オブジェクトの頂点情報を表示する

    Keyword Arguments:
        arg_objectname {str} -- 指定オブジェクト名 (default: {"Default"})

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

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

    # 指定オブジェクトが存在するか確認する
    if selectob == None:
        # 指定オブジェクトが存在しない場合は処理しない
        return False
    
    # 不要なオブジェクトを選択しないように
    # 全てのオブジェクトを走査する
    for ob in bpy.context.scene.objects:
        # 非選択状態に設定する
        ob.select_set(False)

    # 指定のオブジェクトのみを選択状態にする
    selectob.select_set(True)

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

    # 編集モードに移行する
    # モード切替のマニュアル
    # (https://docs.blender.org/api/current/bpy.ops.object.html#bpy.ops.object.mode_set)
    bpy.ops.object.mode_set(mode='EDIT', toggle=False)

    # メッシュデータを取得する
    # メッシュアクセスのマニュアル
    # (https://docs.blender.org/api/current/bmesh.types.html?highlight=bmedge#bmesh.types.BMesh)
    meshdata = bmesh.from_edit_mesh(selectob.data)

    # 選択モードを頂点選択モードにする
    meshdata.select_mode = {'VERT'}

    # 頂点を走査する
    # 頂点アクセスのマニュアル
    # (https://docs.blender.org/api/current/bmesh.types.html?highlight=bmedge#bmesh.types.BMVert)
    for v in meshdata.verts:
        # 頂点位置の情報をコンソールに表示する
        print(v.co)

    return True

# 関数の実行例
print("mesh_verts_print")
mesh_verts_print("Cube")

実行の結果、こちらではローカル座標の座標情報が取得できました。
f:id:bluebirdofoz:20210811222805j:plain

pythonでのグローバル座標の取得方法

Pythonスクリプト上で対象オブジェクトのグローバル座標を取得したい場合は変換行列の matrix_world を利用します。
docs.blender.org

変換座標を用いて頂点位置のグローバル座標を表示するスクリプトを作成しました。
・mesh_globalverts_print.cs

# bpyインポート
import bpy
# メッシュ操作のため
import bmesh

# 指定オブジェクトの頂点情報を表示する
def mesh_globalverts_print(arg_objectname="Default") -> bool:
    """指定オブジェクトの頂点情報を表示する

    Keyword Arguments:
        arg_objectname {str} -- 指定オブジェクト名 (default: {"Default"})

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

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

    # 指定オブジェクトが存在するか確認する
    if selectob == None:
        # 指定オブジェクトが存在しない場合は処理しない
        return False
    
    # 不要なオブジェクトを選択しないように
    # 全てのオブジェクトを走査する
    for ob in bpy.context.scene.objects:
        # 非選択状態に設定する
        ob.select_set(False)

    # 指定のオブジェクトのみを選択状態にする
    selectob.select_set(True)

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

    # 編集モードに移行する
    # モード切替のマニュアル
    # (https://docs.blender.org/api/current/bpy.ops.object.html#bpy.ops.object.mode_set)
    bpy.ops.object.mode_set(mode='EDIT', toggle=False)

    # メッシュデータを取得する
    # メッシュアクセスのマニュアル
    # (https://docs.blender.org/api/current/bmesh.types.html?highlight=bmedge#bmesh.types.BMesh)
    meshdata = bmesh.from_edit_mesh(selectob.data)

    # 選択モードを頂点選択モードにする
    meshdata.select_mode = {'VERT'}

    # グローバル座標への変換行列を取得する
    # (https://docs.blender.org/api/current/bpy.types.Object.html#bpy.types.Object.matrix_world)
    matrix_world = selectob.matrix_world

    # 頂点を走査する
    # 頂点アクセスのマニュアル
    # (https://docs.blender.org/api/current/bmesh.types.html?highlight=bmedge#bmesh.types.BMVert)
    for v in meshdata.verts:
        # 頂点位置のグローバル座標情報をコンソールに表示する
        print(matrix_world @ v.co)

    return True

# 関数の実行例
print("mesh_globalverts_print")
mesh_globalverts_print("Cube")

実行の結果、グローバル座標の座標情報が取得できました。
f:id:bluebirdofoz:20210811222817j:plain