Я пытаюсь реализовать обнаружение столкновения Sphere-Plane в 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
которое мы можем упростить до NS + d < r
где N - нормальный вектор плоскости, S - центр сферы, r - радиус сфера и d - расстояние от точки начала. Как рассчитать значение d из моей плоскости и сферы?
bool Sphere::intersects(const Plane& other) const
{
// return other.getNormal() * this->currentPosition + other.getDistance() < this->radius;
}
Существует довольно простая формула для расстояния между точками и плоскими уравнениями
Ax+By+Cz+D=0
(см. Здесь здесь)
Distance = (A*x0+B*y0+C*z0+D)/Sqrt(A*A+B*B+C*C)
где (x0, y0, z0) - точечные координаты. Если нормальный вектор плоскости (A, B, C) нормализуется (единица), то знаменатель может быть опущен.
(Знак расстояния обычно не важен для целей пересечения)
D
в плоскости, этот ответ более эффективен. Отличная работа! Может быть, я буду использовать это.
Мне нужно было то же вычисление в игре, которую я сделал. Это минимальное расстояние от точки до плоскости:
distance = (q - plane.p[0])*plane.normal;
За исключением distance
, все переменные являются трехмерными векторами (я использую простой класс, который я создал с перегрузкой оператора).
distance
: минимальное расстояние от точки до плоскости (скалярное).
q
: точка (трехмерный вектор), в вашем случае это центр сферы.
plane.p[0]
: точка (трехмерный вектор), принадлежащая плоскости. Обратите внимание, что любая точка, принадлежащая плоскости, будет работать.
plane.normal
. нормальная: нормальная к плоскости.
*
Является точечным произведением между векторами. Может быть реализовано в 3D как a*b = ax*bx + ay*by + az*bz
и дает скаляр.
Точечный продукт определяется:
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
и нормалью к плоскости. Тогда косинус - это проекция на нормаль, которая является вертикальным расстоянием от точки до плоскости.