Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/125.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 三维线段与平面相交_C++_Algorithm_Math_Vector_Collision Detection - Fatal编程技术网

C++ 三维线段与平面相交

C++ 三维线段与平面相交,c++,algorithm,math,vector,collision-detection,C++,Algorithm,Math,Vector,Collision Detection,我正在尝试实现一个线段和平面相交测试,它将根据它是否与平面相交而返回true或false。它还将返回直线相交平面上的接触点,如果直线不相交,如果直线分段为光线,则函数仍应返回交点。我使用了Christer Ericson的实时碰撞检测中的信息和代码,但我认为我没有正确地实现它 使用的平面是从三角形的法线和垂直度导出的。找到平面上的交点位置是我想要的,不管它是否位于我用来导出平面的三角形上 该函数的参数如下所示: contact = the contact point on the plane,

我正在尝试实现一个线段和平面相交测试,它将根据它是否与平面相交而返回true或false。它还将返回直线相交平面上的接触点,如果直线不相交,如果直线分段为光线,则函数仍应返回交点。我使用了Christer Ericson的实时碰撞检测中的信息和代码,但我认为我没有正确地实现它

使用的平面是从三角形的法线和垂直度导出的。找到平面上的交点位置是我想要的,不管它是否位于我用来导出平面的三角形上

该函数的参数如下所示:

contact = the contact point on the plane, this is what i want calculated
ray = B - A, simply the line from A to B
rayOrigin = A, the origin of the line segement
normal = normal of the plane (normal of a triangle)
coord = a point on the plane (vertice of a triangle)
以下是我使用的代码:

bool linePlaneIntersection(Vector& contact, Vector ray, Vector rayOrigin, Vector normal, Vector coord) {

    // calculate plane
    float d = Dot(normal, coord);

    if (Dot(normal, ray)) {
        return false; // avoid divide by zero
    }

    // Compute the t value for the directed line ray intersecting the plane
    float t = (d - Dot(normal, rayOrigin)) / Dot(normal, ray);

    // scale the ray by t
    Vector newRay = ray * t;

    // calc contact point
    contact = rayOrigin + newRay;

    if (t >= 0.0f && t <= 1.0f) {
        return true; // line intersects plane
    }
    return false; // line does not
}
bool线平面交点(向量与接触、向量射线、向量射线原点、向量法线、向量坐标){
//计算平面
浮动d=点(正常,坐标);
if(点(法线、光线)){
返回false;//避免被零除
}
//计算与平面相交的定向线光线的t值
浮点t=(d-点(法线,光线原点))/点(法线,光线);
//按t缩放光线
向量newRay=ray*t;
//计算接触点
联系人=光线原点+新光线;

如果(t>0.0f和&t<p>)我可能错了,但是代码中有几个点看起来很可疑。
// calculate plane
float d = Dot(normal, coord);
// Compute the t value for the directed line ray intersecting the plane
float t = (d - Dot(normal, rayOrigin)) / Dot(normal, ray);
这里,您的值
d
对应于平面法线(向量)和空间点(平面上的点)之间的点积。这似乎是错误的。特别是,如果有任何平面通过原点并使用原点作为坐标点,您将结束计算

d = Dot(normal, (0, 0, 0)) = 0
立即返回false。我不确定你打算在这里做什么,但我很确定这不是你的意思

代码中另一个看起来可疑的地方是这一行:

// calculate plane
float d = Dot(normal, coord);
// Compute the t value for the directed line ray intersecting the plane
float t = (d - Dot(normal, rayOrigin)) / Dot(normal, ray);
请注意,您正在计算平面的法向量(向量)和光线的原点(空间中的点)之间的点积。这似乎很奇怪,因为这意味着根据光线在空间中的来源,用于光线的比例因子会发生变化。我建议您再看一次这段代码,看看这是否真的是您的意思


希望这有帮助!

这一切对我来说都很好。我已经独立检查了代数,这对我来说很好

作为示例测试用例:

A = (0,0,1)
B = (0,0,-1)
coord = (0,0,0)
normal = (0,0,1)
这使得:

d = Dot( (0,0,1), (0,0,0)) = 0
Dot( (0,0,1), (0,0,-2)) = -2 // so trap for the line being in the plane passes.
t = (0 - Dot( (0,0,1), (0,0,1) ) / Dot( (0,0,1), (0,0,-2)) = ( 0 - 1) / -2 = 1/2
contact = (0,0,1) + 1/2 (0,0,-2) = (0,0,0) // as expected.

>在@ TePaTeTyPyff的回答之后给出了修正,唯一的问题是执行其他操作之一,即“代码< >代码”(<代码> >,或者<代码>向量运算符。

< p>我回答这个问题是因为它在谷歌上首先提出了一个C++交叉的例子: 代码始终返回false,因为您在此处输入if:

if (Dot(normal, ray)) {
   return false; // avoid divide by zero
}
如果向量垂直,则点积仅为零,这是您希望避免的情况(无相交),并且非零数字在C中为真。
因此,解决方案是求反(!)或做点(…)==0。
在所有其他情况下,将有一个十字路口。

关于交点计算: 平面的所有点X遵循以下等式

点(N,X)=d

其中,N为法线,d可通过将平面的已知点放入方程中来找到

float d = Dot(normal, coord);
在射线上,直线的所有点s都可以表示为点p和给出方向D的向量:

s=p+x*D

因此,如果我们搜索平面中的xs,我们有

点(N,s)=d
点(N,p+x*D)=D

点积a.b转置(a)*b
转置(N)beNt

Nt*(p+x*D)=D
Nt*p+Nt*D*x=D(x标量)
x=(d-Nt*p)/(Nt*d)
x=(d-Dot(N,p))/Dot(N,d)

这给了我们:
float x = (d - Dot(normal, rayOrigin)) / Dot(normal, ray);
float x=(d-点(正常,光线原点))/Dot(正常,光线);
现在我们可以通过在直线方程中加入x来获得交点

s=p+x*D

Vector intersection=rayOrigin+x*射线;

上述代码已更新:
bool linePlaneIntersection(Vector& contact, Vector ray, Vector rayOrigin, 
                           Vector normal, Vector coord) {
    // get d value
    float d = Dot(normal, coord);
if (Dot(normal, ray) == 0) { return false; // No intersection, the line is parallel to the plane }
// Compute the X value for the directed line ray intersecting the plane float x = (d - Dot(normal, rayOrigin)) / Dot(normal, ray);
// output contact point *contact = rayOrigin + normalize(ray)*x; //Make sure your ray vector is normalized return true; }
布尔线平面交点(矢量和接触、矢量光线、矢量光线原点、,
向量法线,向量坐标){
//获得d值
浮点d=点(正常,坐标);
if(点(法线,光线)==0){ return false;//无交点,直线与平面平行 }
//计算与平面相交的定向直线光线的X值 浮点x=(d-点(法线,光线原点))/点(法线,光线);
//输出接点 *contact=rayOrigin+normalize(光线)*x;//确保光线向量已规格化 返回true; }

旁白1:
d值是什么意思?
对于两个向量ab而言,点积实际上返回一个向量在另一个向量上的正交投影长度乘以另一个向量的长度。
但是如果a被归一化(长度=1),点(a,b)ba上的投影长度。对于我们的平面,d给出了平面在法线方向上所有点到原点的方向距离(a为法线)。然后,我们可以通过比较法线(点积)上投影的长度来确定点是否在此平面上。

旁白2:
如何检查光线是否与三角形相交?(U)