形状を囲むOBBを計算 (スクリプト)


物理アシスタント」のスクリプトの機能を使用して、
選択形状を囲むバウンディングボックスを計算します。
このとき、形状にフィットするように傾けたOBB (Oriented Bounding Box)を求めます。

OBBとは ?

OBBとは形状を囲むバウンディングボックスの種類の1つで、
形状に合わせて傾いた姿勢を持つことができます。
OBBは、中心とサイズ、傾きを表す回転行列を持ちます。

OBB情報を計算

以下をスクリプトウィンドウで実行すると、ブラウザで選択された形状の
OBBとしての中心位置/サイズ/回転行列を計算できます。


scene = xshade.scene()
shape = scene.active_shape()

# 物理シーンを作成.
p = scene.create_physics()

# OBBの計算(回転を考慮、ローカル座標で計算).
obbData = p.calc_obb_shape(shape, True, False)
print "中心位置 : " + str(obbData.center)
print "サイズ : " + str(obbData.size)
print "回転行列 : " + str(obbData.rotation)

# 物理シーンを破棄.
p.remove()

「p = scene.create_physics()」で物理シーンを作成、
「p.remove()」で物理シーンを破棄しています。
その間で「obbData = p.calc_obb_shape(shape, True, False)」を呼ぶと、OBBの計算が行われます。
第一引数は形状の参照、
第二引数をTrueにすると回転を考慮、
第三引数をTrueにするとワールド座標としての計算/Falseにするとローカル座標としての計算、となります。
結果が「physics_obb」クラスに戻り値として入ります。
physics_obbの「center」が中心位置、「size」がサイズ、「rotation」が回転行列となります。

形状を囲むOBBとして、直方体を配置

例として、ブラウザで選択された形状に重なるようにOBBの直方体を配置します。

scene = xshade.scene()
shape = scene.active_shape()

# 物理シーンを作成.
p = scene.create_physics()

# OBBの計算(回転を考慮、ローカル座標で計算).
obbData = p.calc_obb_shape(shape, True, False)

# 原点位置に、obbData.sizeのボックスを生成.
box = scene.create_primitive_box("box", 0, True, 1, 1, 1,
  [ obbData.size[0] * 0.5, -obbData.size[1] * 0.5, -obbData.size[2] * 0.5],
  [ obbData.size[0] * 0.5, -obbData.size[1] * 0.5,  obbData.size[2] * 0.5],
  [-obbData.size[0] * 0.5, -obbData.size[1] * 0.5,  obbData.size[2] * 0.5],
  [-obbData.size[0] * 0.5, -obbData.size[1] * 0.5, -obbData.size[2] * 0.5],
  [0, obbData.size[1],  0],
  True, True)

# OBBと位置と回転行列.
boxPos  = obbData.center
boxRotM = obbData.rotation

# 回転行列に位置を加える.
m = [[0 for j in range(4)] for i in range(4)]
for i in range(4):
  for j in range(4):
    m[i][j] = boxRotM[i][j]

m[3][0] = boxPos[0]
m[3][1] = boxPos[1]
m[3][2] = boxPos[2]

# box形状に行列として反映.
box.transform(m)

# 物理シーンを破棄
p.remove()

これを実行すると、以下のように選択形状を囲む直方体が配置されます。

Translate »