我正在尝试用 C++ 实现球面碰撞检测。我有一个 Vector3、Plane 和 Sphere 类。
#include "Vector3.h"
#ifndef PLANE_H
#define PLANE_H
class Plane
{
public:
Plane(Vector3, float);
Vector3 getNormal() const;
protected:
float d;
Vector3 normal;
};
#endif
我知道平面的方程是
Ax + By = Cz + D = 0
,我们可以将其简化为 N.S + d < r
,其中 N 是平面的法向量,S 是球体的中心,r 是球体的半径,d 是距离从原点。如何根据平面和球体计算 d 值?
bool Sphere::intersects(const Plane& other) const
{
// return other.getNormal() * this->currentPosition + other.getDistance() < this->radius;
}
我需要在我制作的游戏中进行相同的计算。这是从点到平面的最小距离:
distance = (q - plane.p[0])*plane.normal;
除了
distance
,所有变量都是 3D 向量(我使用一个通过运算符重载制作的简单类)。
distance
:点到平面的最小距离(标量)。
q
:点(3D 向量),在您的情况下是球体的中心。
plane.p[0]
:属于平面的点(3D 向量)。请注意,属于平面的任何点都可以工作。
plane.normal
:垂直于平面。
*
是向量之间的点积。可以在 3D 中实现为 a*b = a.x*b.x + a.y*b.y + a.z*b.z
并产生标量。
点积定义为:
a*b = |a| * |b| * cos(angle)
或者,在我们的例子中:
a = q - plane.p[0]
a*plane.normal = |a| * |plane.normal| * cos(angle)
由于
plane.normal
是酉 (|plane.normal| == 1
):
a*plane.normal = |a| * cos(angle)
a
是从点 q
到平面上一点的向量。 angle
是 a
与平面法线之间的角度。那么,余弦就是法线的投影,也就是点到平面的垂直距离。
用平面方程计算点平面距离有相当简单的公式
Ax+By+Cz+D=0
(这里eq.10)
Distance = (A*x0+B*y0+C*z0+D)/Sqrt(A*A+B*B+C*C)
其中 (x0,y0,z0) 是点坐标。如果您的平面法向量 (A,B,C) 已标准化(单位),则可以省略分母。
(对于交叉路口来说,距离标志通常并不重要)
但是,如果平面是由一组顶点定义的,并且其边的大小不均匀,该怎么办?