Направление перемещения в теореме о разделяющей оси

Я реализовал теорему о разделяющей оси в Java. Само обнаружение столкновений работает отлично. Но я застрял, когда дело доходит до разрешения столкновения.

мой способ получить перевод выглядит так:

public float getOverlap(final Projection other) {
    float start = m_min > other.m_min ? m_min : other.m_min;
    float end = m_max < other.m_max ? m_max : other.m_max;
    float translation = end - start;
    return translation;
}

Допустим, проекция двух прямоугольников на рисунке выглядит следующим образом.

R1.min = 2
R1.max = 8
R2.min = 5
R2.max = 11

Разделительная ось перевода

Когда я проверяю R1 против R2, перевод будет 3. Когда я проверяю R2 и R1, перевод также будет 3

теперь я добавляю перевод к нормализованной оси

Normalized axis = Vector(1,0)
Translation Vector = Vector(1,0)*3 = Vector (3,0)

И теперь R1 и R2 перемещаются на 3 точки вправо, но они могут двигаться в разных направлениях. R1 должен переместить вектор (-3,0), R2 должен переместить вектор (3,0).

Как я могу вычислить правильное направление?

1 ответ

Решение

Мое решение:

Я вычитаю центральный вектор R1 из центрального вектора R2, строю скалярное произведение к тестируемой оси и инвертирую перевод, если скалярное произведение меньше 0

Vector centerR1(R1.x,R1.y);
Vector centerR2(R2.x,R2.y);

Vector R1toR2 = centerR2 - centerR1;

if(R1toR2.dot(axis)<0){
  translation = -translation
}

"Когда вектор (R1toR2) указывает в отрицательном направлении, инвертируйте перевод"

Просто отправлю здесь еще один ответ, который решил это для меня.

Решение с точечным произведением у меня не сработало, хотя вы, кажется, проверяете, соответствует ли точка < 0 в вашем ответе, тогда как везде я видел, что чек >= 0, поэтому я не уверен, что это что-нибудь изменит.

Я решил, что верну либо положительное, либо отрицательное перекрытие в моем getOverlapфункция, и это укажет направление разрешения. Это будет зависеть от того, меньше ли min первого объекта, чем min второго объекта или нет.

// Check for overlap of two 1 dimensional lines
function getLineOverlap(min1, max1, min2, max2) {
    let min = Math.max(min1, min2);
    let max = Math.min(max1, max2);

    // if negative, no overlap
    let result = Math.max(max - min, 0);

    // add positive/negative sign depending on direction of overlap
    return result * ((min1 < min2) ? 1 : -1);
};

Если это по-прежнему не работает, вам может потребоваться умножить полученный вектор разрешения на -1.

Я получил это решение из этого ответа на стек.

Другие вопросы по тегам