4

「視線」タイプのテストにブレンダーを使用しようとしています。このために、ray_cast 関数 (blender ゲーム エンジンにはないレイキャスティング関数) を使用したいと考えています。何を試しても、コードをまったく機能させることができません。

(a と b の 2 つのオブジェクトがあるとします)

a から b に ray_cast しようとすると、ブレンダーを開いてからその関数を初めて使用し、開始位置または終了位置の少なくとも 1 つが原点にある場合にのみ、正しい答えを得ることができます。1 つのオブジェクトを移動した後に行われる後続の ray_cast は、シーンを手動で更新した後でも結果を変更しません (つまり、最初と同じ結果が得られます)。始点または終点が原点にない状態でキャストしようとすると、null (Vector<0,0,0>, Vector<0,0,0>, -1) が返されます。

Object.closest_point_on_mesh などの他のレンダー関数でも同様のことが起こることに気付きました... 誰か助けてくれませんか? 以下は、rayCasting に使用するコードです。

#

import bpy

def main():

a = bpy.data.objects['a']
b = bpy.data.objects['b']

x = a.ray_cast(a.location,b.location)
print(x[0])

main()

#

4

2 に答える 2

3

さて、ray_cast 関数は、開始座標と終了座標の両方が object.ray_cast 内のオブジェクトのローカル座標系にあることを想定しています。これは、グローバル/ワールド座標である a.location および b.location 座標をローカル座標に変換する必要があることを意味します。 .

こちらです:

globalcoordinate = Vector((x, y, z))
localcoordinateforobject = (globalcoordinate - object.location) * object.matrix_world.inverted()

通常は上記のように matrix_world を使用しますが、この回転とスケールが適用されていない (Ctrl-A) 回転/スケールされたオブジェクトでは機能しません。そこで、多くのアドオンで使用するこのコードを共有します。

def adapt(selobj):

    # Rotating / panning / zooming 3D view is handled here.
    # Creates a matrix.
    if selobj.rotation_mode == "AXIS_ANGLE":
        # object rotation_quaternionmode axisangle
        ang, x, y, z =  selobj.rotation_axis_angle
        matrix = Matrix.Rotation(-ang, 4, Vector((x, y, z)))
    elif selobj.rotation_mode == "QUATERNION":
        # object rotation_quaternionmode euler
        w, x, y, z = selobj.rotation_quaternion
        x = -x
        y = -y
        z = -z
        quat = Quaternion([w, x, y, z])
        matrix = quat.to_matrix()
        matrix.resize_4x4()
    else:
        # object rotation_quaternionmode euler
        ax, ay, az = selobj.rotation_euler
        mat_rotX = Matrix.Rotation(-ax, 4, 'X')
        mat_rotY = Matrix.Rotation(-ay, 4, 'Y')
        mat_rotZ = Matrix.Rotation(-az, 4, 'Z')
        if selobj.rotation_mode == "XYZ":
            matrix = mat_rotX * mat_rotY * mat_rotZ
        elif selobj.rotation_mode == "XZY":
            matrix = mat_rotX * mat_rotZ * mat_rotY
        elif selobj.rotation_mode == "YXZ":
            matrix = mat_rotY * mat_rotX * mat_rotZ
        elif selobj.rotation_mode == "YZX":
            matrix = mat_rotY * mat_rotZ * mat_rotX
        elif selobj.rotation_mode == "ZXY":
            matrix = mat_rotZ * mat_rotX * mat_rotY
        elif selobj.rotation_mode == "ZYX":
            matrix = mat_rotZ * mat_rotY * mat_rotX
    # handle object scaling
    sx, sy, sz = selobj.scale
    mat_scX = Matrix.Scale(sx, 4, Vector([1, 0, 0]))
    mat_scY = Matrix.Scale(sy, 4, Vector([0, 1, 0]))
    mat_scZ = Matrix.Scale(sz, 4, Vector([0, 0, 1]))
    matrix = mat_scX * mat_scY * mat_scZ * matrix

    return matrix

オブジェクト「selobj」の「matrix」と呼ばれる右変換行列を返します。上記のコード例の object.matrix_world の代わりに使用してください。

于 2013-08-19T11:05:11.950 に答える
2

これで問題が解決するはずです:

def main():
a = bpy.data.objects['a']
b = bpy.data.objects['b']


localA = a.matrix_world.inverted() * a.location
localB = a.matrix_world.inverted() * b.location

print(localA, localB)

(location, normal, index) = a.ray_cast(localA, localB)

print(location, normal, index)

# reselect the originally selected face
if(index > 0):
    a.data.polygons[index].select = True
于 2013-10-18T11:56:21.690 に答える