Тест пересечения кубической сферы? - PullRequest
5 голосов
/ 02 января 2011

Какой самый простой способ сделать это?Я потерпел неудачу в математике, и я нашел довольно сложные формулы в Интернете ... я надеюсь, если есть какая-то более простая?

Мне просто нужно знать, перекрывает ли сфера куб, мне все равно, в какой точкеон делает это и т. д.

Я также надеюсь, что он воспользуется тем, что обе фигуры симметричны.

Редактировать: куб выровнен прямо воси x, y, z

Ответы [ 3 ]

23 голосов
/ 02 января 2011

Недостаточно взглянуть на полупространства, вы должны рассмотреть также точку ближайшего приближения:

Заимствование обозначения Адама:

Предполагается, что выровнено по осикуб и пусть C1 и C2 - противоположные углы, S - центр сферы, а R - радиус сферы, и оба объекта являются сплошными:

inline float squared(float v) { return v * v; }
bool doesCubeIntersectSphere(vec3 C1, vec3 C2, vec3 S, float R)
{
    float dist_squared = R * R;
    /* assume C1 and C2 are element-wise sorted, if not, do that now */
    if (S.X < C1.X) dist_squared -= squared(S.X - C1.X);
    else if (S.X > C2.X) dist_squared -= squared(S.X - C2.X);
    if (S.Y < C1.Y) dist_squared -= squared(S.Y - C1.Y);
    else if (S.Y > C2.Y) dist_squared -= squared(S.Y - C2.Y);
    if (S.Z < C1.Z) dist_squared -= squared(S.Z - C1.Z);
    else if (S.Z > C2.Z) dist_squared -= squared(S.Z - C2.Z);
    return dist_squared > 0;
}
19 голосов
/ 02 января 2011

Джим Арво имеет алгоритм для этого в Graphics Gems 2, который работает в N-измерениях. Я полагаю, что вы хотите "случай 3" внизу этой страницы: http://www.ics.uci.edu/~arvo/code/BoxSphereIntersect.c который очищен для вашего случая:

bool BoxIntersectsSphere(Vec3 Bmin, Vec3 Bmax, Vec3 C, float r) {
  float r2 = r * r;
  dmin = 0;
  for( i = 0; i < 3; i++ ) {
    if( C[i] < Bmin[i] ) dmin += SQR( C[i] - Bmin[i] );
    else if( C[i] > Bmax[i] ) dmin += SQR( C[i] - Bmax[i] );     
  }
  return dmin <= r2;
}
0 голосов
/ 23 июля 2016
// Assume clampTo is a new value. Obviously, don't move the sphere
closestPointBox = sphere.center.clampTo(box)

isIntersecting = sphere.center.distanceTo(closestPointBox) < sphere.radius

Все остальное - просто оптимизация.

Вау, -2.Жесткая толпа.Хорошо, вот реализация three.js, которая в основном говорит одно и то же слово в слово.https://github.com/mrdoob/three.js/blob/dev/src/math/Box3.js

intersectsSphere: ( function () {

    var closestPoint;

    return function intersectsSphere( sphere ) {

        if ( closestPoint === undefined ) closestPoint = new Vector3();

        // Find the point on the AABB closest to the sphere center.
        this.clampPoint( sphere.center, closestPoint );

        // If that point is inside the sphere, the AABB and sphere intersect.
        return closestPoint.distanceToSquared( sphere.center ) <= ( sphere.radius * sphere.radius );

    };

} )(),
...