3D中的光线和方形/矩形交叉

时间:2012-01-10 23:26:08

标签: python graphics geometry intersection

平。制作游戏并且正在寻找仅在3D空间中的正方形或矩形的光线交叉。有搜索网络,发现了很多解决方案,但我无法理解的是在2D中有线和线段交叉脚本,但我无法弄清楚必须使它成为3D。 从它与正方形或矩形相交的一侧并不重要,但它必须能够反转交点矢量,以便以后可以测试距离se的距离,如果它发生在同一光线交叉点上的其他交叉点之前或之后。 / p>

非常感谢python或其他类似脚本语言中的任何示例

编辑:不知道必须修改2D以显示一个问题,但是制作了一个新的并发布了两者。

//this is the exaple it test a ray onto a plane then look to se if that point is in the rectangle and saves it to test for distanse later
list Faces; //triangle faces
list Points; //

vector FindPoint(){
    //calcute the point of intersection onto the plane and returns it
    //if it can intersect
    //else return ZERO_VECTOR
}

integer point-in-quadrilateral(){
    //return 1 if the point is in the rectangular on the plane
    //else return 0
}

default{

    state_entry(){
        integer n = (Faces != []); //return number of elements
        integer x = 0;
        while(x < n){
            vector intersection = FindPoint( FromList(Faces, x) ); //take     out a element and runs it trough the function
            if(intersection != ZERO_VECTOR){
                integer test = point-in-quadrilateral( FromList(Faces,     x) ); //find out if the point is in rectangular
                if(test == 1){ //if so
                    Points += intersection; //save the point
                }
            }
            ++x;
        }

        float first; //the distanse to the box intersection
        integer l = (Points != []);
        integer d;
        while(d < l){
            if(Dist( FromList(Points, d) ) < first) //if the new distanse     is less then first
                return 0; //then end script
            ++d;
        }
    }

}


//this is the 2D version
vector lineIntersection(vector one, vector two, vector three, vector four){
float bx = two.x - one.x;
float by = two.y - one.y;
float dx = four.x - three.x;
float dy = four.y - three.y; 
float b_dot_d_perp = bx*dy - by*dx;
if(b_dot_d_perp == 0.0) {
    return ZERO_VECTOR;
}
float cx = three.x-one.x; 
float cy = three.y-one.y;
float t = (cx*dy - cy*dx) / b_dot_d_perp; 
if(LineSeg){ //if true tests for line segment
    if((t < 0.0) || (t > 1.0)){
        return ZERO_VECTOR;
    }
    float u = (cx * by - cy * bx) / b_dot_d_perp;
    if((u < 0.0) || (u > 1.0)) {
        return ZERO_VECTOR;
    }
}

return <one.x+t*bx, one.y+t*by, 0.0>; 

}

3 个答案:

答案 0 :(得分:7)

当您定义具有点(=矢量)和方向矢量的光线以及带有点(=矢量)的矩形和表示边的两个矢量时,解决方案非常简单。

假设光线定义为R0 + t * D,其中R0是光线的原点,D是表示其方向的单位矢量,t是其长度。

矩形可以用角点P0表示,两个矢量S1S2表示边(它们的长度等于边的长度)。你需要另一个与其表面垂直的向量N,它等于S1S2的叉积的单位向量。

现在,假设光线与P处的矩形相交。然后,光线方向D必须与法线N形成非零角度。这可以通过选中D.N < 0来验证。

要找到交叉点,请假设P = R0 + a * D(该点必须在光线上)。您需要立即找到a的值。找到向量P0P。这必须与N垂直,这意味着P0P.N = 0减少到a = ((P0 - R0).N) / (D.N)

现在你需要检查点是否在矩形内。为此,请沿Q1的{​​{1}} P0PS1 Q2的{​​{1}}投影P0P。然后,内部点的条件是S20 <= length(Q1) <= length(S1)

此方法适用于任何类型的平行四边形,不仅适用于矩形。

答案 1 :(得分:3)

为R3中的直线创建矢量方程,然后求解您正在测试它的矩形平面中该直线的交点。在那之后,它很简单,可以测试解决方案是否位于边界内。

解决方案的参数t可以通过以下方式找到:

t = (a * (x0 - rx) + b * (y0 - ry) + c * (x0 - rz)) / (a * vx + b * vy + c * vz)

其中:

a(x - x0) + b(y - y0) + c(z - z0) = 0

是矩形所在平面的等式

<x, y, z> = <rx + vx * t, ry + vy * t, rz + vz * t>

是相关线的矢量方程。

请注意:

<rx, ry, rz>

是矢量方程的初始点,

<vx, vy, vz>

是上式的方向向量

之后,将参数t插入矢量方程将为您提供测试距离的要点。

enter image description here

答案 2 :(得分:1)

您没有说3D中的方形/矩形是否与坐标轴对齐。 假设3D矩形 R 在空间中任意定向,这里有一种方法。 首先,使用包含 R 的平面对您的光线 r 进行交互。这可以通过要求a来实现 比例因子 s 乘以 r 并将其放在 R 的平面上,并求解 s 。这会在飞机上为您提供一个 p 点。现在将平面和 R p 投影到其中一个坐标上 飞机{ xy yz zx }。您只需避免垂直于平面的法线向量投影,这始终是可能的。然后解决投影平面中的四边形点问题。

在开始之前,检查您的线段是否位于 R 的3D平面中,如果是,则单独处理。