Нахождение MTV (минимальный вектор перевода) с использованием теоремы о разделяющей оси

Так что я пытался заставить обнаружение столкновений и реагирование работать в моем игровом проекте, используя теорему о разделяющей оси. Мне удалось обнаружить столкновение, но я не могу понять, как на него реагировать. Я пытаюсь найти минимальный вектор перевода, но я не уверен, как сделать его фактическим вектором, чтобы я мог рассчитать, как реагировать на столкновение. Я прочитал учебник за учебником, и я посмотрел на многие ранее заданные вопросы здесь, но я не могу понять, как его реализовать. Мне очень трудно понять, как найти и использовать MTV, так что, если кто-нибудь действительно сможет помочь мне понять, и, возможно, дать мне какой-то пример, чтобы я мог понять это в реализации, а не просто в теории, это было бы очень приветствую, и я прошу прощения за любые неудобства. Мой код успешно обнаруживает столкновения, и здесь он ниже:

//NOTE: This is within the HitPolygon class, so "this" is referencing itself as a polygon
public Projection project(Vector2D axis){

    float min = axis.dot(this.getVertices().get(0));
    float max = min;
    Vector2D vecMax  = new Vector2D(0, 0), vecMin = new Vector2D(0, 0);

    for(int i = 1; i < this.getVertices().size(); i++){
        float p = axis.dot(this.getVertices().get(i));
        if(p < min){
            min = p;
            vecMin = this.getVertices().get(i);
        }
        if(p > max){
            max = p;
            vecMax = this.getVertices().get(i);
        }
    }

    Projection result = new Projection(min, max, vecMin, vecMax, axis);

    return result;

}

public boolean contains(Projection p1, Projection p2){
    return(p1.min >= p2.min && p1.min <= p2.max) || (p1.max >= p2.min && p1.max <= p2.max);
}

public boolean overlap(Projection a, Projection b){
    if(contains(a, b)) return true;
    if(contains(b, a)) return true;

    return false;
}

public boolean collide(HitPolygon b){

    ArrayList<Vector2D> axes1 = this.getAxes(0);
    ArrayList<Vector2D> axes2 = b.getAxes(0);

    for(int i = 0; i < axes1.size(); i++){
        Vector2D axis = axes1.get(i);
        Projection p1 = this.project(axis), p2 = b.project(axis);

        if(!overlap(p1, p2)) return false;
        else{
            float start = p1.min > p2.min ? p1.min : p2.min;
            float end = p1.max < p2.max ? p1.max : p2.max;
            float translation = end - start;
            //translation might be the MTV, more or less, but it's not a vector and I don't know how to turn it into one.
        }
    }

    for(int i = 0; i < axes2.size(); i++){
        Vector2D axis = axes2.get(i);
        Projection p1 = this.project(axis), p2 = b.project(axis);
        if(!overlap(p2, p1)) return false;
        else{

        }
    }
    System.out.println("collide");
    return true;
}

А вот простой класс проекции:

class Projection{
    public Vector2D minVec, maxVec;
    public float min, max;
    public Vector2D axis = new Vector2D(0, 0);
    public Projection(float min, float max, Vector2D minVec, Vector2D maxVec, Vector2D axis){
        this.min = min;
        this.max = max;
        this.minVec = minVec;
        this.maxVec = maxVec;
        this.axis = axis;
    }

    public float minDot(){
        return axis.dot(minVec);
    }

    public float maxDot(){
        return axis.dot(maxVec);
    }
}

Если понадобится какой-либо дополнительный код, я буду рад его предоставить. Простите, что я не понимаю, как найти и использовать MTV, но любая помощь действительно ценится. Спасибо!

1 ответ

Решение

Это очень просто на самом деле. Вам нужно знать углы осей, которые вы использовали, и глубину, с которой сталкиваются два объекта в каждом случае (глубина - это длина области предполагаемого столкновения).

Конвертировать все данные в вектор с помощью следующей техники:

var vecX = Math.cos(axisAngle) * deepness;
var vecY = Math.sin(axisAngle) * deepness;

Затем сложите векторы:

var sumX = vec1X + vec2X + ...;
var sumY = vec1Y + vec2Y + ...;

После этого вы получите вектор суммы, который является вектором смещения, который вам нужно использовать (из-за магии)

введите описание изображения здесь

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