MRが楽しい

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

Blender2.9で利用可能なpythonスクリプトを作る その78(バウンドボックスの頂点情報をグローバル座標に変換する)

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

バウンドボックスの頂点情報をグローバル座標に変換する

通常、ローカル座標で取得されるバウンドボックスをグローバル座標に変換して同様のデータ形式で返却します。
バウンドボックスから取得できる頂点情報は Vector 型に変換することでグローバル座標への変換行列を適用できます。
docs.blender.org
docs.blender.org

サンプルプロジェクト

以下のような異なるスケールを設定した階層構造下の Mesh オブジェクトを作成しました。
f:id:bluebirdofoz:20210813232255j:plain
f:id:bluebirdofoz:20210813232306j:plain

サンプルコード

オブジェクトのバウンドボックスを取得し、その頂点をグローバル座標に変換して返却します。
・Script_get_object_globalboundbox.py

# bpyインポート
import bpy

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

# グローバル座標に変換されたオブジェクトのバウンドボックスを取得する
def get_object_globalboundbox(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
    
    # 指定オブジェクトの境界情報を取得する
    # オブジェクトのインタフェース
    # (https://docs.blender.org/api/current/bpy.types.Object.html#bpy.types.Object.bound_box)
    target_boundbox = selectob.bound_box

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

    # 頂点座標の加算
    for index in range(8):
        # 一度Vecotorに変換して座標を変換する
        globalvert = (matrix_world @ Vector(target_boundbox[index]))

        # 結果を返却リストに代入する
        globalbound_box[index][0] = globalvert[0]
        globalbound_box[index][1] = globalvert[1]
        globalbound_box[index][2] = globalvert[2]

    return globalbound_box

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

# 比較確認のため、ローカル座標のバウンドボックスも表示する
local_bound_box = bpy.data.objects.get("Cube").bound_box
print("local_bound_box")
for local_bound_pos in local_bound_box:
    # 頂点位置の情報をコンソールに表示する
    print(Vector(local_bound_pos))

f:id:bluebirdofoz:20210813232320j:plain

利用時の注意点

あくまでバウンドボックスの頂点を座標変換しているだけなので回転を考慮したバウンドボックスの範囲は取得できません。
f:id:bluebirdofoz:20210813232331j:plain