Объект в сфере (ограничивающая сфера), хочет, чтобы он ограничивал движение внутри сферы - PullRequest
0 голосов
/ 21 апреля 2011

Так как я могу ограничить движение моего объекта ТОЛЬКО в сфере? Я пробовал с ограничительной рамкой и методом пересечения, но он не работает?

Редактировать 1:

это был не вопрос ... я спрашивал: у меня есть 2 ограничивающие сферы, одна большая и одна маленькая, малая будет двигаться внутри большой, но я не хочу, чтобы она выходила за пределы большой ограничивающей сферы. Как это сделать? я делаю это?

Ответы [ 3 ]

1 голос
/ 21 апреля 2011

Существует более быстрый способ убедиться, что расстояние между центрами не превышает разницу в радиусах.Не требуется каждый раз брать квадратный корень.

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

local max_distance = big.radius - small.radius
max_distance_squared = max_distance*max_distance    

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

local dx = big.center_x - small.center_x
local dy = big.center_y - small.center_y
if (dx*dx + dy*dy <= max_distance_squared)
  # great
else
  # explode

Сэкономленное время может немного увеличить частоту кадров или скорость моделирования.

0 голосов
/ 21 апреля 2011
if (Vector3.Distance(bigSphere, smallSphere) < bigSphereradius - smallSphereradius) {
 // inside
}

Или используйте класс BoundingSphere:

http://msdn.microsoft.com/en-us/library/bb195373.aspx

пс. если векторы нормированы, то и радиусы тоже должны быть:)

0 голосов
/ 21 апреля 2011

Расстояние центра маленькой сферы от центра большой сферы никогда не должно быть больше (BigRadius - SmallRadius).Если вы хотите рассчитать положение, в котором установлен контакт, вы можете масштабировать вектор движения на отношение разницы в радиусах, необходимых для установления контакта, и общей разницы в радиусах от начальной точки до конечной точки (если движение не достаточно велико, чтобыпересечь плоскость, определяемую одной из осей большой ограничивающей сферы)

class Sphere {
    public Vector3 Pos;
    public double Radius;
}

void Test() 
{
    Sphere big = new Sphere() { Pos = new Vector3(0, 0, 0), Radius = 10.0 };
    Sphere small = new Sphere() { Pos = new Vector3(8, 0, 0), Radius = 1.0 };
    Vector3 move = new Vector3(0, 10, 0);

    // new position without check, if within sphere ok
    Vector3 newPos = small.Pos + move;
    if (Vector3.Distance(newPos, big.Pos) < big.Radius - small.Radius)
        return;

    // diff in radius to contact with outer shell
    double space = (big.Radius - small.Radius) - Vector3.Distance(small.Pos, big.Pos);

    // movement past moment of hitting outer shell
    double far = Vector3.Distance(newPos, big.Pos) - (big.Radius - small.Radius);

    // scale movement by ratio to get movement to hit shell
    move = move * (space / (space + far));
    newPos = small.Pos + move;
}

Я думаю, что это сработает, ЕСЛИ движение не пересекает плоскость, определенную одной из координат большой сферы, и выходит наружу.Может быть, вы могли бы добавить специальную проверку для того, чтобы знак движения X, Y или Z отличался от большого. POS - маленький. POS (относительное положение центра маленькой сферы к центру большой сферы) X, Y или Z ...

...