レイから形状の表面と衝突する交点位置を取得 (スクリプト)


物理アシスタント」のスクリプトの機能を使用して、
「レイ」(Ray)と特定の形状の面と衝突する交点位置/法線ベクトルを計算することができます。
レイは、位置と向き(方向ベクトル)を持つものです。
シーンに形状として存在するものではなく、概念になります。
レイトレーシング」の「レイ」と同じ意味になります。

このレイによる形状の面への衝突処理を「レイキャスト」と呼びます。

カメラの視線方向から、選択形状の表面へのレイキャスト

ここでは例として、カメラの視点と注視点をレイとして、
視線の先にある選択形状との衝突を計算します。
カメラの視点と注視点は、ワールド座標での値を計算します。
以下のスクリプトになります。

import numpy

scene = xshade.scene()

# ローカル座標でのカメラの位置と注視点.
eye    = scene.camera.eye
target = scene.camera.target

# カメラのローカル・ワールド変換行列.
lwMat = numpy.matrix(numpy.identity(4))
if scene.camera.camera_object != None:
  lwMat = numpy.matrix(scene.camera.camera_object.local_to_world_matrix)

# カメラの位置と注視点をワールド座標に変換.
eye    = numpy.dot(numpy.array([eye[0], eye[1], eye[2], 1.0]), lwMat)
target = numpy.dot(numpy.array([target[0], target[1], target[2], 1.0]), lwMat)

eye    = [eye[0,0], eye[0,1], eye[0,2]]
target = [target[0,0], target[0,1], target[0,2]]

ここで計算された「eye」が視点位置、「target」が目標点位置になります。

レイを計算

カメラの視点と注視点より、以下のようにレイとしての位置と方向ベクトルを計算します。

# レイの位置.
rayPos = eye

# 視線ベクトルをレイの方向ベクトルにする.
rayDir = numpy.array(target) -  numpy.array(eye)

# rayDirを単位ベクトルにする.
len = numpy.linalg.norm(rayDir)
if len != 0.0:
  rayDir /= len
rayDir = [rayDir[0], rayDir[1], rayDir[2]]

rayPosがレイの位置、rayDirがレイの方向ベクトルになります。

選択形状とのレイキャスト

# 選択形状.
shape = xshade.scene().active_shape()

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

# 物理シーンに形状追加開始.
p.begin_creating()

# shapeを静的な物体として物理シーンに追加.
# 引数は順番に、衝突形状はメッシュ(3)、剛体の種類は静的(1)、質量1.0、マージン0.0.
# これはワールド座標として格納される点に注意.
p.append_rigidbody_shape(shape, 3, 1, 1.0, 0.0)

# 物理シーンに形状追加終了.
p.end_creating()

# レイキャストを行う.
rayHitData = p.do_raycast(rayPos, rayDir)
if rayHitData != None:
  print "交差形状 [" + str(rayHitData.hit_shape.name) + "]"
  print "交差位置 " + str(rayHitData.position)
  print "交差位置での面の法線 " + str(rayHitData.normal)
else:
  print "交差しませんでした。"

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

物理計算では、まず「物理シーン」を作成する必要があります。
「p = scene.create_physics()」として物理シーンを作成。
戻り値 p が「physics」クラスの参照になります。
最終的に破棄する際は「p.remove()」のようにします。

この物理シーンに、「p.begin_creating()」から「p.end_creating()」で挟むようにして物理形状を配置します。
「p.append_rigidbody_shape(shape, 3, 1, 1.0, 0.0)」で、第一引数のshapeをポリゴンメッシュ(第二引数の3)の衝突として物理シーンに配置しています。
第三引数の1は「静的な剛体」、第四引数は質量、第五引数はマージンの指定になります。

各種パラメータの詳細はスクリプトリファレンス(http://help.shade3d.jp/ja/support/PythonScriptRefDoc/)のphysicsクラスを参照するようにしてください。

rayHitData = p.do_raycast(rayPos, rayDir)

でレイキャスト処理を実行します。
第一引数でレイの位置、第二引数でレイの方向ベクトルを指定します。
戻り値は、「physics_rayhit」クラスが返ります。
Noneの場合は交差無しです。
「rayHitData.hit_shape」に交差した形状(shapeクラス)の参照。
「rayHitData.position」が交差位置。
「rayHitData.normal」が交差位置での法線が入ります。

このように、スクリプトを使用することで
特定の形状へのレイキャスト計算を行うことができます。

Translate »