Направление перемещения в теореме о разделяющей оси
Я реализовал теорему о разделяющей оси в 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
.
Я получил это решение из этого ответа на стек.