【问题标题】:C++ Plane Sphere Collision DetectionC++ 平面球体碰撞检测
【发布时间】:2014-04-01 08:55:28
【问题描述】:

我正在尝试在 C++ 中实现 Sphere-Plane 碰撞检测。我有一个 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;
}

【问题讨论】:

  • 基本上你想比较球心到平面的距离和球体的半径。寻找关于点到平面的距离的数学。在平面上投影该点也可以为您提供一个计算与平面距离的好位置。叉积和点积可以帮助计算。

标签: c++ geometry collision-detection


【解决方案1】:

我在制作的游戏中需要相同的计算。这是点到平面的最小距离:

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 到平面中某个点的向量。 anglea 与平面法线之间的角度。那么余弦就是法线上的投影,也就是点到平面的垂直距离。

【讨论】:

    【解决方案2】:

    平面方程的点平面距离有一个相当简单的公式

    Ax+By+Cz+D=0(eq.10 here)

    Distance = (A*x0+B*y0+C*z0+D)/Sqrt(A*A+B*B+C*C)
    

    其中 (x0,y0,z0) 是点坐标。如果您的平面法向量 (A,B,C) 已归一化(单位),则可以省略分母。

    (距离的标志通常对于交叉路口并不重要)

    【讨论】:

    • 如果将D存储在平面上,这个答案效率更高。好工作!也许我会用它。
    • D 的这个值是浮点数还是我的 Plane 的构造函数的参数,其中我有 Plane(const Vector3&, float)?
    • 我认为这是真的,但请检查平面文档或构造函数主体
    • 我建议添加一个构造函数Plane(const Vector3 &amp;normal, const Vector3 &amp;belongingPoint),并在D = -(normal*belongingPoint) 内部计算。
    • OK,它将是有效的D
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-15
    • 1970-01-01
    • 1970-01-01
    • 2015-10-06
    • 2013-02-28
    相关资源
    最近更新 更多