物体の接地をスクリプトで計算

ここでは「斜めに傾いた板に直方体を接地する (物理アシスタント)」で書いた処理を、
スクリプトを使って行います。

以下のような板状の形状「ground」を固定とし、トーラス状の形状「torus」をgroundの平面に接地させる例を
スクリプトで求めていきます。

落下する形状が、初めに衝突する位置を取得

落下する形状「torus」が、静的な剛体の「ground」に初めに衝突するときの位置を取得します。

scene = xshade.scene()

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

# 物理形状の格納開始.
p.begin_creating()

# 静的な剛体として、"ground"の形状を物理シーンに追加.
shape = scene.get_shape_by_name("ground")
# 引数は直方体(2)、剛体の種類は静的(1)、質量1.0、マージン0.0
phyGround = p.append_rigidbody_shape(shape, 2, 1, 1.0, 0.0)

# 動的な剛体として、"torus"の形状を物理シーンに追加.
# 引数は直方体(2)、剛体の種類は動的(0)、質量1.0、マージン0.0
shape = scene.get_shape_by_name("torus")
phyTorus = p.append_rigidbody_shape(shape, 2, 0, 1.0, 0.0)
phyTorus.trigger_stop = True  # 衝突判定を有効化.

# 物理形状の格納終了.
p.end_creating()

# 時間を進める.
minPassTime = 0.01
while p.pass_time < 10.0:
  p.step(minPassTime, 10, True)
  if p.has_contact:       # 衝突があるか判定.
    print "pos : " + str(phyTorus.position)
    break

# 形状の実体化 (コメントアウトしてます).
# p.convert_shapes(None, True)

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

「p.begin_creating()」から「p.end_creating()」の間で
静的な剛体として「ground」、動的な剛体として「torus」を「append_rigidbody_shape」関数を使って物理シーンに登録しています。
「torus」を登録後「phyTorus.trigger_stop = True」と指定することで、
このphyTorus形状と他の形状との衝突を知ることができるようになります。
「p.step(minPassTime, 10, True)」にて第一引数の秒数だけ時間を進めます。
そのあとに「p.has_contact」をチェックし、Trueが返される場合に衝突が発生したことになります。

このスクリプトを実行すると、直方体(OBB)としてTorusを囲んで
時間を進めた時の衝突位置を検出/表示します。

「p.remove()」の前に「p.convert_shapes」を以下のように記述すると
物理運動後の衝突したときの形状を実体化します。

p.convert_shapes(None, True)

実体化すると以下のようになりました。

正面図では衝突していないように見えますが、これはOBBとして衝突させているためです。
OBBとしては、以下のように角がgroundの形状と衝突した状態になっています。

ここではOBBとしての1点での衝突のみ検出できました。
完全に接地した状態を、次で計算します。

完全に接地した状態まで時間を進める

ここでは単純に
「p.has_contact」がTrueを返した後に少し物理時間を進めることにします。

時間を進めて実体化する処理を以下のように記載しました。

# 時間を進める.
minPassTime = 0.01
while p.pass_time < 10.0:
  p.step(minPassTime, 10, True)
  if p.has_contact:       # 衝突があるか判定.
    break

# 時間を0.1秒進める.
p.step(0.1, 10, True)

# 形状の実体化.
p.convert_shapes(None, True)

「p.step」で時間を小刻みに進めて衝突で抜けた後、
「p.step(0.1, 10, True)」として少しだけ時間を進めるようにしました。
形状を実体化すると、以下のように接地した状態になりました。

このときの数値としての位置と回転行列は、torus形状の「phyTorus」から以下のように取得できます。

newPos      = phyTorus.position  # 形状の中心位置.
newRotation = phyTorus.rotation  # 形状の回転行列.
Translate »