MRが楽しい

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

Blender2.9で利用可能なpythonスクリプトを作る その79(グローバル座標のバウンドボックスを作成して取得する)

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

グローバル座標のバウンドボックスを作成して取得する

通常、ローカル座標で取得されるバウンドボックスをグローバル座標で作成して返却します。
メッシュの頂点情報からバウンドボックスを作成するため、以下のスクリプトと比較して、回転が考慮されますが処理時間がかかります
bluebirdofoz.hatenablog.com

サンプルコード

オブジェクトのグローバル座標のバウンドボックスを作成して返却します。
・Script_get_object_globalboundbox.py

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

# Vector変換インポート
from mathutils import Vector

# グローバル座標のバウンドボックスを取得する
def get_boundbox_global(arg_objectname="Default") -> list:
    """グローバル座標のバウンドボックスを取得する

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

    Returns:
        list -- バウンドボックス(float 多次元配列 8 * 3) 例:((0.0, 0.0, 0.0), (0.0, 0.0, 0.0), ...)
    """
    
    # 返却用のリストを作成する
    globalbound_box = [[0.0, 0.0, 0.0] for i in range(8)]

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

    # 指定オブジェクトが存在するか確認する
    if selectob == None:
        # 指定オブジェクトが存在しない場合は処理しない
        return globalbound_box
    
    # 不要なオブジェクトを選択しないように
    # 全てのオブジェクトを走査する
    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

    # 各軸の最小、最大座標を取得する
    x_min = 0.0
    x_max = 0.0
    y_min = 0.0
    y_max = 0.0
    z_min = 0.0
    z_max = 0.0

    # 頂点数を取得する
    vert_count = 0

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

        if vert_count == 0:
            x_min = global_vert[0]
            x_max = global_vert[0]
            y_min = global_vert[1]
            y_max = global_vert[1]
            z_min = global_vert[2]
            z_max = global_vert[2]
        else:
            if x_min > global_vert[0]:
                x_min = global_vert[0]
            if x_max < global_vert[0]:
                x_max = global_vert[0]
            if y_min > global_vert[1]:
                y_min = global_vert[1]
            if y_max < global_vert[1]:
                y_max = global_vert[1]
            if z_min > global_vert[2]:
                z_min = global_vert[2]
            if z_max < global_vert[2]:
                z_max = global_vert[2]
        
        # 頂点数のカウントアップ
        vert_count = vert_count + 1

    # 頂点が存在したか確認する
    if vert_count == 0:
        # 頂点が存在しない場合は処理しない
        return globalbound_box
    
    # バウンドボックス情報の作成
    globalbound_box[0] = [x_max, y_max, z_max]
    globalbound_box[1] = [x_max, y_max, z_min]
    globalbound_box[2] = [x_max, y_min, z_max]
    globalbound_box[3] = [x_max, y_min, z_min]
    globalbound_box[4] = [x_min, y_max, z_max]
    globalbound_box[5] = [x_min, y_max, z_min]
    globalbound_box[6] = [x_min, y_min, z_max]
    globalbound_box[7] = [x_min, y_min, z_min]

    return globalbound_box

# 関数の実行例
global_bound_box = get_boundbox_global(arg_objectname="Cube")
print("global_bound_box")
for global_bound_pos in global_bound_box:
    # 頂点位置の情報をコンソールに表示する
    print(Vector(global_bound_pos))

f:id:bluebirdofoz:20210814232716j:plain