我正在尝试实现一个线段和平面相交测试,它将返回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
}
在我的测试中,它永远不会真实......任何想法?
答案 0 :(得分:7)
我正在回答这个问题,因为当被要求提供光线交叉的c ++示例时,它首先出现在Google上。)
代码总是返回false,因为您输入if here:
if (Dot(normal, ray)) {
return false; // avoid divide by zero
}
如果矢量是垂直的,则点积仅为零,这是您要避免的情况(无交点),而非零数字在C中为真。
因此解决方案是否定(!)或做Dot(...)== 0
在所有其他情况下,将有一个交叉点。
到交叉点计算: 平面的所有点 X 遵循等式
点(N,X)= d
N 是法线, d 可以通过将平面的已知点放在等式中来找到。
float d = Dot(normal, coord);
在光线上,线条的所有点 s 可以表示为点 p ,并且向量的方向为 D :< / p>
s = p + x * D
因此,如果我们搜索飞机中的 x s ,我们就有
点(N,s)= d
点(N,p + x * D)= d
点积 ab 是转置(a)* b 。
让转置(N)为 Nt 强>
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);
我们现在可以通过将 x 放在线方程中来获得交点
s = p + x * D
Vector intersection = rayOrigin + x*ray;
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;
}
答案 1 :(得分:2)
我可能错了,但代码中有一些看似非常可疑的地方。首先,请考虑以下这一行:
// calculate plane
float d = Dot(normal, coord);
此处,您的值d
对应于平面法线(矢量)和空间点(平面上的点)之间的点积。这似乎是错的。特别是,如果你有任何平面穿过原点并使用原点作为坐标点,你将最终计算
d = Dot(normal, (0, 0, 0)) = 0
并立即返回false。我不确定你打算在这里做什么,但我很确定这不是你的意思。
代码中另一个似乎可疑的地方是这一行:
// Compute the t value for the directed line ray intersecting the plane
float t = (d - Dot(normal, rayOrigin)) / Dot(normal, ray);
请注意,您正在计算平面法线向量(矢量)和光线原点(空间中的点)之间的点积。这看起来很奇怪,因为它意味着根据光线在空间中的起源,您用于光线的缩放因子会发生变化。我建议再看一下这段代码,看看这是不是你的意思。
希望这有帮助!
答案 2 :(得分:1)
这一切对我来说都很好。我已经独立检查了代数,这对我来说很好。
作为示例测试用例:
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.
因此,考虑到@ templatetypedef的回答后的修改,我能看到问题的唯一区域是执行其他操作之一,无论是Dot()
还是Vector
运算符。 / p>