所以我正在阅读此页面上的内容(http://gamedeveloperjourney.blogspot.com/2009/04/point-plane-collision-detection.html)
作者提到
d = - D3DXVec3Dot(&vP1, &vNormal);
其中vP1是平面上的点,vNormal是平面的法线。我很好奇这是如何让你与世界起源的距离,因为结果总是为0.此外,为了清楚(因为我对平面方程的d部分仍然有点朦胧),是一个平面方程式中从一条直线穿过世界原点到平面原点的距离?
答案 0 :(得分:6)
在一般情况下,点p
和平面之间的距离可以通过
<p - p0, normal>
其中<a, b>
是点积运算
<a, b> = ax*bx + ay*by + az*bz
并且p0
是飞机上的一个点。
当n
为单位长度时,矢量与它之间的点积是法线上矢量投影的(带符号)长度
您报告的公式只是点p
为原点时的特殊情况。在这种情况下
distance = <origin - p0, normal> = - <p0, normal>
这种平等是形式错误的,因为点积是关于向量而不是点......但仍然保持数字。写下明确的公式,你就得到了
(0 - p0.x)*n.x + (0 - p0.y)*n.y + (0 - p0.z)*n.z
与
相同- (p0.x*n.x + p0.y*n.y + p0.z*n.z)
确实存储飞机的好方法是保存正常n
和k = <p0, n>
的值,其中p0
是飞机上的任何点({{1}的值}与您选择的平面无关。)
答案 1 :(得分:2)
结果并非总是为零。如果飞机穿过原点,结果将只为零。 (这里假设飞机不通过原点。)
基本上,你会从原点到飞机上的某个点给出一条线。 (即你有一个从原点到vP1的矢量)。这个矢量的问题在于它很可能是倾斜的并且在平面上的某个很远的地方而不是飞机上最近的点。所以,如果你只是花了vP1的长度,你会得到一个太大的距离。
您需要做的是将vP1投影到您知道垂直于平面的某个矢量上。那当然是vNormal。因此,取vP1和vNormal的点积,除以vNormal的长度,你就得到了答案。 (如果他们足够友好地给你一个已经是第一级的vNormal,那么就不需要分开了。)
答案 2 :(得分:1)
你可以用拉格朗日乘数来解决这个问题:
您知道飞机上最近的点必须是以下形式:
c = p + v
其中c
是最近的点,而v
是沿着平面的向量(因此与n
正交,正常)。您正在尝试找到具有最小范数(或范数平方)的c
。因此,您试图最小化dot(c,c)
,v
与n
正交(因此dot(v,n) = 0
)。
因此,设置拉格朗日:
L = dot(c,c) + lambda * ( dot(v,n) )
L = dot(p+v,p+v) + lambda * ( dot(v,n) )
L = dot(p,p) + 2*dot(p,v) + dot(v,v) * lambda * ( dot(v,n) )
并将v
(并设置为0)的导数取得:
2 * p + 2 * v + lambda * n = 0
您可以通过上面的等式求解lambda,并通过n
生成两边来获取
2 * dot(p,n) + 2 * dot(v,n) + lambda * dot(n,n) = 0
2 * dot(p,n) + lambda = 0
lambda = - 2 * dot(p,n)
再次注意dot(n,n) = 1
和dot(v,n) = 0
(因为v
在平面中,n
与它正交)。然后将lambda
替换回来获取:
2 * p + 2 * v - 2 * dot(p,n) * n = 0
并解决v
得到:
v = dot(p,n) * n - p
然后将其重新插入c = p + v
以获取:
c = dot(p,n) * n
此向量的长度为|dot(p,n)|
,符号表示该点是在原点的法线向量的方向,还是从原点的反方向。