4

我一直在尝试使用搅拌机进行“视线”类型测试。为此,我想使用 ray_cast 函数(不在搅拌机游戏引擎中的 raycasting 函数)。无论我尝试什么,我都无法让代码正常工作。

(假设我有 2 个对象,a 和 b)

当我尝试从 a 到 b 的 ray_cast 时,如果这是我打开搅拌机后第一次使用该功能,并且开始或结束位置中至少有一个位于原点,我只能得到正确的答案。即使在手动更新场景后,在移动一个对象后完成的后续 ray_casts 也不会改变结果(如,我得到的结果与第一次相同)。如果我尝试在起点或终点不在原点的情况下进行投射,则返回 null (Vector<0,0,0>, Vector<0,0,0>, -1)

我注意到其他渲染函数也会发生类似的事情,例如 Object.closest_point_on_mesh 等……有人可以帮我吗?下面是我用于光线投射的代码。

#

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 中对象的 LOCAL 坐标系中,这意味着您的 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 回答